2

This is my first wrapper class and I think it is a hard one. I tried to put this all into one query and it failed because of a junction object. I then put it into 2 queries using components and it failed again because of SOQL query limits. My only hope is that a wrapper class will allow me to pull all the data into one list so I can present it in a VF page. Below are my two SOQL queries with a for loop in a single class. I know there is some redundancy but I am still learning. Any help to either use this to write a 2nd class as a wrapper or to rewrite this to be a wrapper class would be most helpful. Thanks in advance.

Current Apex Class:

public class MonthlySeizureController1{
    public task taskRec                 { get; set; }
    public task taskRec1                { get; set; }
    public List<Case__c> theCases              { get; set; } // this was the ca reference
    public Map<Id, Business__c> businessMap    { get; set; } // this was the bus1 reference
    public MonthlySeizureController1(ApexPages.StandardController sc){
        taskRec = new task (ActivityDate__c = Date.today().addMonths(-1));
        taskRec1       = new task (ActivityDate__c = Date.today());
        // get the supply chain chases in the last month be careful of 10k cases in this result
        this.theCases = querySupplyChainCasesBetweenDates(taskRec.ActivityDate__c, taskRec1.ActivityDate__c);
        // collect the ids of the businesses in these cases
        Set<Id> businessIds = new Set<Id>();
        for (Case__c c : theCases) {
            for (BusinessCasesAssociation__c bca : c.BusinessCasesAssociations__r) {
                businessIds.add(bca.Business__c); 
            }
        } 
        // get the businesses related to these cases and assign them to the variable in the controller
        this.businessMap = queryBusinesses(businessIDs);
    }
    public MonthlySeizureController1() {
        // why do we have this constructor too? consider moving the logic above in here and then calling 'this();' in the first line of the standard controller constructor
    }
    private Map<Id, Business__c> queryBusinesses(Set<Id> businessIDs) { 
        Map<Id, Business__c> result =  new Map<Id, Business__c>([SELECT Id
                                                                    , Name
                                                                    , Business_Name__c
                                                                    , Business_Type__c
                                                                    , (SELECT Street__c
                                                                            , Business_City__c
                                                                            , State_Province__c
                                                                            , Country__c
                                                                            , Zip_Postal_Code__c 
                                                                        FROM BPR_Business_Addresses__r)
                                                                    , (SELECT Number_Type__c
                                                                            , Number__c 
                                                                        FROM Business_Phone_Numbers__r)
                                                                    , (SELECT Email_Bus__c 
                                                                        FROM Email_Businesses__r)
                                                                FROM Business__c
                                                                WHERE (Id = :businessIDs)]);
        return result;
    }
    private List<Case__c> querySupplyChainCasesBetweenDates(Date lowerDate, Date upperDate) { 
        List<Case__c> cases = [SELECT Id
                                    , Name
                                    , CreatedDate
                                    , LastModifiedDate
                                    , Owner.FirstName
                                    , Owner.LastName
                                    , Notification_Date__c
                                    , Incident_City__c
                                    , Incident_Country__r.Name
                                    , Total_Product__c
                                    , Comments_Postal_Express__c
                                    , (SELECT RecordType.Name
                                            , Container__c
                                            , Ship_Date__c
                                            , Date_of_Retention__c
                                            , Carrier__c
                                            , Port_of_Loading__c
                                            , Port_of_Discharge__c
                                            , Container_Type__c
                                            , Place_of_Retention__c
                                            , Vessel__c
                                            , Master_BOL__c
                                            , House_BOL__c
                                        FROM Incident_Locations__r)
                                    , (SELECT Brand__c
                                            , Product_Detail__c
                                            , Product_Types__c
                                            , Total_Product_Quantity__c 
                                        FROM Products__r)
                                    , (SELECT Business__c
                                            , Case__c
                                            , Business__r.Business_Name__c
                                            , Business__r.Business_Type__c 
                                        FROM BusinessCasesAssociations__r)
                                    , (SELECT Subject_Name__r.Subject_Name__c
                                            , Subject_Name__r.Subject_Type__c 
                                        FROM Subject_for_Cases__r)
                                FROM Case__c
                                WHERE Supply_Chain_Type__c = 'SEA'
                                    AND Notification_Date__c >= :lowerDate
                                    AND Notification_Date__c <= :upperDate
                                ORDER BY Notification_Date__c ASC];
        return cases;
    }
    public PageReference next(){
        PageReference nextpage = new PageReference('/apex/securityreport1ppv');
        return nextpage;
    }
    public PageReference next1(){
        PageReference nextpage = new PageReference('/apex/securityreport1sap');
        return nextpage;
    }
}

VF PAGE:

<apex:page standardController="Case__c" extensions="MonthlySeizureController1">
<style type="text/css">
    table.myTable{
        border-collapse: collapse;
    }
    table.myTable td{
        border: 1px solid black;
        padding: 5px;
    }
    table.myTable th{
        border: 2px solid black;
        padding: 5px;
    }
    a.linkAsBtn,
    a.linkAsBtn:hover {
        text-decoration: none;
        padding: 3px 6px;
    }
</style>
<apex:form >
<apex:panelGrid columns="8" id="dates1">
    <b>Start Date: </b><apex:inputfield value="{!taskRec.ActivityDate__c}" required="true"/>
    <b>End Date: </b><apex:inputfield value="{!taskRec1.ActivityDate__c}" required="true"/>
    &nbsp;<apex:commandLink value="Submit" rerender="test" styleClass="btn linkAsBtn"/>  
    <apex:commandLink value="Printable View" action="{!next}" id="cmdNext" target="_blank" styleClass="btn linkAsBtn"/> 
    <apex:commandLink value="Save as PDF" action="{!next1}" id="cmdNext1" target="_blank" styleClass="btn linkAsBtn"/>
</apex:panelGrid>
<apex:outputPanel id="test">  
    <table class="myTable">
        <tr>
            <th>BPR Case</th>
            <th>BP MGR</th>
            <th>SHIPPING DATE/SEIZURE DATE</th>
            <th>NOTIFY DATE</th>
            <th>SEIZURE LOCATION</th>
            <th>CONTAINER NO.</th>
            <th>CARRIER</th>
            <th>TRADING CO.</th>
            <th>SHIPPER CO.</th>           
            <th>SHIPPER NAME</th>
            <th>SHIPPER ADDRESS</th>
            <th>SHIPPER PHONE</th>
            <th>SHIPPER EMAIL</th>            
            <th>PORT OF LOADING</th>                      
            <th>MANUFACTURER/PROVIDER</th>
            <th>MANUFACTURER/PROVIDER ADDRESS</th>            
            <th>CONSIGNEE BUSINESS</th>
            <th>CONSIGNEE NAME</th>
            <th>CONSIGNEE ADDRESS</th> 
            <th>CONSIGNEE PHONE</th>
            <th>CONSIGNEE EMAIL</th>           
            <th>PORT OF DISCHARGE</th>            
            <th>NOTIFY PARTY</th>
            <th>NOTIFY PARTY ADDRESS</th> 
            <th>NOTIFY PARTY PHONE</th>            
            <th>PRODUCT</th>
            <th>AMOUNT (pairs, items)</th>
            <th>CONTAINER STATS</th>
            <th>ADDITIONAL INFORMATION</th>
        </tr>
    <apex:repeat value="{!theCases}" var="c" id="case">
        <tr>
            <td>
            <a href="https://mydomain.my.salesforce.com/{!c.Id}">{!c.name}</a>
            </td>
            <td>
            <apex:outputText value="{!c.Owner.FirstName}"></apex:outputText>&nbsp;<apex:outputText value="{!c.Owner.LastName}"></apex:outputText>
            </td>
            <td>
            <apex:repeat value="{!c.Incident_Locations__r}" var="loc">
                <apex:outputText value="{0,date,MM'-'dd'-'yyyy}"><apex:param value="{!loc.Ship_Date__c}"/></apex:outputText>/&nbsp;
                <apex:outputText value="{0,date,MM'-'dd'-'yyyy}"><apex:param value="{!loc.Date_of_Retention__c}"/></apex:outputText><br></br>
            </apex:repeat>
            </td>
            <td>
            <apex:outputText value="{0,date,MM'-'dd'-'yyyy}"><apex:param value="{!c.Notification_Date__c}"/></apex:outputText>
            </td>
            <td>
            <apex:outputText value="{!c.Incident_City__c}"></apex:outputText>/&nbsp;
            <apex:outputText value="{!c.Incident_Country__r.Name}"></apex:outputText>
            </td>
            <td>
            <apex:repeat value="{!c.Incident_Locations__r}" var="loc">
                <apex:outputText value="{!loc.Container__c}"></apex:outputText><br></br>
            </apex:repeat>
            </td>
            <td>
            <apex:repeat value="{!c.Incident_Locations__r}" var="loc">
                <apex:outputText value="{!loc.Carrier__c}"></apex:outputText><br></br>
            </apex:repeat>
            </td>
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                <apex:outputText value="{!bus.Business__r.Business_Name__c}" rendered="{!bus.Business__r.Business_Type__c = 'Trading Company'}"></apex:outputText><br></br>
            </apex:repeat>
            </td>   
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                <apex:outputText value="{!bus.Business__r.Business_Name__c}" rendered="{!bus.Business__r.Business_Type__c = 'Exporter'}"></apex:outputText>
            </apex:repeat>  
            </td>                                  
            <td>
            <apex:repeat value="{!c.Subject_for_Cases__r}" var="sub">
                <apex:outputText value="{!sub.Subject_Name__r.Subject_Name__c}" rendered="{!sub.Subject_Name__r.Subject_Type__c = 'Exporter'}"></apex:outputText><br></br>
            </apex:repeat>
            </td>
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="businessCaseAssociation">
                <apex:outputField value="{!businessMap[businessCaseAssociation.Business__c].BPR_Business_Addresses__r.Street__c}"/><br></br>
            </apex:repeat>
            </td>   
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="businessCaseAssociation">
                <c:business_shipper_contact_info2 BusinessID="{!businessMap[businessCaseAssociation.Business__c]}" /><br></br>
            </apex:repeat>
            </td>
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="businessCaseAssociation">
                <c:business_shipper_contact_info3 BusinessID="{!businessMap[businessCaseAssociation.Business__c]}" /><br></br>
            </apex:repeat>
            </td>                         
            <td>
            <apex:repeat value="{!c.Incident_Locations__r}" var="loc">
                <apex:outputText value="{!loc.Port_of_Loading__c}"></apex:outputText><br></br>
            </apex:repeat>
            </td>                                              
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                <apex:outputText value="{!bus.Business__r.Business_Name__c}" rendered="{!bus.Business__r.Business_Type__c = 'Factory/Manufacturer'}"></apex:outputText><br></br>
            </apex:repeat>
            </td>
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                MANUFACTURER/PROVIDER ADDRESS
            </apex:repeat>
            </td>               
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                <apex:outputText value="{!bus.Business__r.Business_Name__c}" rendered="{!bus.Business__r.Business_Type__c = 'Importer'}"></apex:outputText><br></br>
            </apex:repeat>
            </td> 
            <td>
            <apex:repeat value="{!c.Subject_for_Cases__r}" var="sub">
                <apex:outputText value="{!sub.Subject_Name__r.Subject_Name__c}" rendered="{!sub.Subject_Name__r.Subject_Type__c = 'Importer'}"></apex:outputText><br></br>
            </apex:repeat>
            </td> 
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                CONSIGNEE ADDRESS
            </apex:repeat>
            </td>
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                CONSIGNEE PHONE
            </apex:repeat>
            </td>
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                CONSIGNEE EMAIL
            </apex:repeat>
            </td>                                    
            <td>
            <apex:repeat value="{!c.Incident_Locations__r}" var="loc">
                <apex:outputText value="{!loc.Port_of_Discharge__c}"></apex:outputText><br></br>
            </apex:repeat>
            </td>                                    
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                <apex:outputText value="{!bus.Business__r.Business_Name__c}" rendered="{!bus.Business__r.Business_Type__c = 'Notify Party'}"></apex:outputText><br></br>
            </apex:repeat>
            </td> 
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                NOTIFY PARTY ADDRESS
            </apex:repeat>
            </td> 
            <td>
            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                NOTIFY PARTY PHONE
            </apex:repeat>
            </td>                                                                                                 
            <td>
            <apex:repeat value="{!c.Products__r}" var="pro">
                <apex:outputText value="{!pro.Brand__c}"></apex:outputText>&nbsp;<apex:outputText value="{!pro.Product_Types__c}"></apex:outputText>&nbsp;(<apex:outputText value="{0,number,###,###}"><apex:param value="{!pro.Total_Product_Quantity__c}"/></apex:outputText>)<br></br>
            </apex:repeat>
            </td>
            <td>
                <apex:outputText value="{!c.Total_Product__c}"></apex:outputText>
            </td>
            <td>
            <apex:repeat value="{!c.Incident_Locations__r}" var="loc">
                <apex:outputText value="{!loc.Container_Type__c}"></apex:outputText><br></br>
            </apex:repeat>
            </td>
            <td>
                <apex:outputText value="{!c.Comments_Postal_Express__c}"></apex:outputText>
            </td>            
         </tr>              
    </apex:repeat>
    </table>
</apex:outputPanel>
</apex:form>
</apex:page>

VF Component:

<apex:component controller="MonthlySeizureController1" access="global">
<apex:attribute id="recordID" assignTo="{!recordID}" name="BusinessID" type="Id" description="The Business's SF Id"/>
    <apex:repeat value="{!bus1}" var="addr1">
            <apex:outputText value="{!addr1.Street__c}"></apex:outputText>&nbsp;<apex:outputText value="{!addr1.Business_City__c}"></apex:outputText>&nbsp;<apex:outputText value="{!addr1.State_Province__c}"></apex:outputText>&nbsp;<apex:outputText value="{!addr1.Country__c}"></apex:outputText>&nbsp;<apex:outputText value="{!addr1.Zip_Postal_Code__c}"></apex:outputText>
    </apex:repeat>       
</apex:component>
  • 1
    By "SOQL query limits" do you mean you couldn't get the query to work or that you git a governor limit such as the 10,000 row limit? Also you need to explain what objects you want in the same list (and how they relate if at all) and explain your data structure a bit more. – Keith C Mar 23 '16 at 19:21
  • @Keith C, good question. I am getting the following error System.LimitException: Too many SOQL queries: 101 It points to the bus1 as causing it to go over. If I remove that it works fine. The main objects I am working with here are the Case__c object and the Business__c object. There is a junction object connecting them which is called BusinessCasesAssociations__c. I have a for loop in the bus1 call above that links them using the Business__c.BusinessCasesAssociations__c field to the Business__c.Id. I hope this helps. If you need more info, please let me know. Thanks. – Nathan Mar 23 '16 at 21:14
  • 1
    I don't see why you are hitting that governor limit with the code you have posted; in my experience Visualforce caches values from the controller i.e. will only call ca and bus1 once. – Keith C Mar 23 '16 at 23:01
  • I added my VF page above. I believe it has to do with the layout that I am trying to accomplish along with relationship of all the objects. Hope this helps. Thanks. – Nathan Mar 23 '16 at 23:39
  • Still don't see why the governor limit is hit... – Keith C Mar 23 '16 at 23:56
5

Unless you're caching the result from the first request to the get; member on the controller every single time the VF page references the { get; member, it'll fire the query contained in the getter again. This can quickly hit a query limit.

Better to either store the result or use a method of your own to do the work and store the result. My example does the latter. I rewrote your controller extension to do the queries for the Case__c and Business__c data in the constructor. The Business__c results are stored in a map to allow you to use array syntax in the VF page to get the value from the map by Business__c.Id in the context of the repeater over Case__c (which has the Business__c.Id on some its child records).

public class MonthlySeizureController1{

    public task taskRec                 { get; set; }
    public task taskRec1                { get; set; }

    public List<Case__c> theCases              { get; set; } // this was the ca reference
    public Map<Id, Business__c> businessMap    { get; set; } // this was the bus1 reference

    public MonthlySeizureController1(ApexPages.StandardController sc){

        // no idea why these are tasks, when they could just be date types on the controller
        oneMonthAgoTask = new task (ActivityDate__c = Date.today().addMonths(-1));
        todayTask       = new task (ActivityDate__c = Date.today());

        // get the supply chain chases in the last month
        // be careful of 10k cases in this result
        this.theCases = querySupplyChainCasesBetweenDates(oneMonthAgoTask.ActivityDate__c, todayTask.ActivityDate__c);

        // collect the ids of the businesses in these cases
        Set<Id> businessIds = new Set<Id>();
        for (Case__c c : theCases) {
            for (BusinessCasesAssociation__c bca : c.BusinessCasesAssociations__r) {
                businessIds.add(bca.Business__c); 
            }
        } 

        // get the businesses related to these cases 
        // and assign them to the variable in the controller
        this.businessMap = queryBusinesses(businessIDs);

    }

    public MonthlySeizureController1() {
        // why do we have this constructor too?
        // consider moving the logic above in here and then calling 
        // this(); in the first line of the standard controller constructor
    }

    private Map<Id, Business__c> queryBusinesses(Set<Id> businessIDs) { 

        Map<Id, Business__c> result =  new Map<Id, Business__c>{[SELECT Id
                                                                    , Name
                                                                    , Business_Name__c
                                                                    , Business_Type__c
                                                                    , (SELECT Street__c
                                                                            , Business_City__c
                                                                            , State_Province__c
                                                                            , Country__c
                                                                            , Zip_Postal_Code__c 
                                                                        FROM BPR_Business_Addresses__r)
                                                                    , (SELECT Number_Type__c
                                                                            , Number__c 
                                                                        FROM Business_Phone_Numbers__r)
                                                                    , (SELECT Email_Bus__c 
                                                                        FROM Email_Businesses__r)
                                                                FROM Business__c
                                                                WHERE (Id = :businessIDs)]};

        return result;
    }

    private List<Case__c> querySupplyChainCasesBetweenDates(Date lowerDate, Date upperDate) { 
        List<Case__c> cases = [SELECT Id
                                    , Name
                                    , CreatedDate
                                    , LastModifiedDate
                                    , Owner.FirstName
                                    , Owner.LastName
                                    , Notification_Date__c
                                    , Incident_City__c
                                    , Incident_Country__r.Name
                                    , Total_Product__c
                                    , Comments_Postal_Express__c
                                    , (SELECT RecordType.Name
                                            , Container__c
                                            , Ship_Date__c
                                            , Date_of_Retention__c
                                            , Carrier__c
                                            , Port_of_Loading__c
                                            , Port_of_Discharge__c
                                            , Container_Type__c
                                            , Place_of_Retention__c
                                            , Vessel__c
                                            , Master_BOL__c
                                            , House_BOL__c
                                        FROM Incident_Locations__r)
                                    , (SELECT Brand__c
                                            , Product_Detail__c
                                            , Product_Types__c
                                            , Total_Product_Quantity__c 
                                        FROM Products__r)
                                    , (SELECT Business__c
                                            , Case__c
                                            , Business__r.Business_Name__c
                                            , Business__r.Business_Type__c 
                                        FROM BusinessCasesAssociations__r)
                                    , (SELECT Subject_Name__r.Subject_Name__c
                                            , Subject_Name__r.Subject_Type__c 
                                        FROM Subject_for_Cases__r)
                                FROM Case__c
                                WHERE Supply_Chain_Type__c = 'SEA'
                                    AND Notification_Date__c >= :lowerDate
                                    AND Notification_Date__c <= :upperDate
                                ORDER BY Notification_Date__c ASC];
        return cases;
    }

    public PageReference next(){
        PageReference nextpage = new PageReference('/apex/securityreport1ppv');
        return nextpage;
    }
    public PageReference next1(){
        PageReference nextpage = new PageReference('/apex/securityreport1sap');
        return nextpage;
    }
}

VF Page Highlights

The important things to note here are referencing the new theCases list on the controller in the outer repeater <apex:repeat value="{!theCases}" var="c" id="case"> and the usage of the array syntax to get the data from the Business__c map to pass to the VF component or reference directly:

<apex:repeat value="{!c.BusinessCasesAssociations__r}" var="businessCaseAssociation">
    <!-- use the businessMap in the controller to show the business data for this view -->
    <apex:outputField value="{!businessMap[businessCaseAssociation.Business__c].Name}" />
    <apex:outputField value="{!businessMap[businessCaseAssociation.Business__c].Business_Type__c}" />
    <apex:outputField value="{!businessMap[businessCaseAssociation.Business__c].Business_Name__c}" />

    <!-- or pass the business__c record from the businessMap itself to the component -->
    <!-- example assumes the component has a parameter on it for 'theBusiness' of type Business__c -->
    <c:business_shipper_contact_info theBusiness="{!businessMap[businessCaseAssociation.Business__c]}" /><br></br>
</apex:repeat>

VF Markup (greatly trimmed)

<apex:page standardController="Case__c" extensions="MonthlySeizureController1">
    <style type="text/css">
        table.myTable {
            border-collapse: collapse;
        }

        table.myTable td {
            border: 1px solid black;
            padding: 5px;
        }

        table.myTable th {
            border: 2px solid black;
            padding: 5px;
        }

        a.linkAsBtn,
        a.linkAsBtn:hover {
            text-decoration: none;
            padding: 3px 6px;
        }
    </style>
    <apex:form>
        <apex:panelGrid columns="8" id="dates1">
            <b>Start Date: </b>
            <apex:inputfield value="{!taskRec.ActivityDate__c}" required="true" />
            <b>End Date: </b>
            <apex:inputfield value="{!taskRec1.ActivityDate__c}" required="true" /> &nbsp;
            <apex:commandLink value="Submit" rerender="test" styleClass="btn linkAsBtn" />
            <apex:commandLink value="Printable View" action="{!next}" id="cmdNext" target="_blank" styleClass="btn linkAsBtn" />
            <apex:commandLink value="Save as PDF" action="{!next1}" id="cmdNext1" target="_blank" styleClass="btn linkAsBtn" />
        </apex:panelGrid>
        <apex:outputPanel id="test">
            <table class="myTable">
                <tr>
                    <th>BPR Case</th>
                    <th>BP MGR</th>
                    <th>SHIPPING DATE/SEIZURE DATE</th>
                    <th>NOTIFY DATE</th>
                    <th>SEIZURE LOCATION</th>
                    <th>CONTAINER NO.</th>
                    <th>CARRIER</th>
                    <th>TRADING CO.</th>
                    <th>SHIPPER CO.</th>
                    <th>SHIPPER NAME</th>
                    <th>SHIPPER ADDRESS</th>
                    <th>SHIPPER PHONE</th>
                    <th>SHIPPER EMAIL</th>
                    <th>PORT OF LOADING</th>
                    <th>MANUFACTURER/PROVIDER</th>
                    <th>MANUFACTURER/PROVIDER ADDRESS</th>
                    <th>CONSIGNEE BUSINESS</th>
                    <th>CONSIGNEE NAME</th>
                    <th>CONSIGNEE ADDRESS</th>
                    <th>CONSIGNEE PHONE</th>
                    <th>CONSIGNEE EMAIL</th>
                    <th>PORT OF DISCHARGE</th>
                    <th>NOTIFY PARTY</th>
                    <th>NOTIFY PARTY ADDRESS</th>
                    <th>NOTIFY PARTY PHONE</th>
                    <th>PRODUCT</th>
                    <th>AMOUNT (pairs, items)</th>
                    <th>CONTAINER STATS</th>
                    <th>ADDITIONAL INFORMATION</th>
                </tr>
                <apex:repeat value="{!theCases}" var="c" id="case">
                    <tr>
                        <td>
                            <a href="https://theDomain.my.salesforce.com/{!c.Id}">{!c.name}</a>
                        </td>
                        <td>
                            <apex:outputText value="{!c.Owner.FirstName}"></apex:outputText>&nbsp;
                            <apex:outputText value="{!c.Owner.LastName}"></apex:outputText>
                        </td>
                        <td>
                            <apex:repeat value="{!c.Incident_Locations__r}" var="loc">
                                <apex:outputText value="{0,date,MM'-'dd'-'yyyy}">
                                    <apex:param value="{!loc.Ship_Date__c}" /></apex:outputText>/&nbsp;
                                <apex:outputText value="{0,date,MM'-'dd'-'yyyy}">
                                    <apex:param value="{!loc.Date_of_Retention__c}" /></apex:outputText><br></br>
                            </apex:repeat>
                        </td>
                        <td>
                            <apex:outputText value="{0,date,MM'-'dd'-'yyyy}">
                                <apex:param value="{!c.Notification_Date__c}" /></apex:outputText>
                        </td>
                        <td>
                            <apex:outputText value="{!c.Incident_City__c}"></apex:outputText>/&nbsp;
                            <apex:outputText value="{!c.Incident_Country__r.Name}"></apex:outputText>
                        </td>
                        <td>
                            <apex:repeat value="{!c.Incident_Locations__r}" var="loc">
                                <apex:outputText value="{!loc.Container__c}"></apex:outputText><br></br>
                            </apex:repeat>
                        </td>
                        <td>
                            <apex:repeat value="{!c.Incident_Locations__r}" var="loc">
                                <apex:outputText value="{!loc.Carrier__c}"></apex:outputText><br></br>
                            </apex:repeat>
                        </td>
                        <td>
                            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                                <apex:outputText value="{!bus.Business__r.Business_Name__c}" rendered="{!bus.Business__r.Business_Type__c = 'Trading Company'}"></apex:outputText><br></br>
                            </apex:repeat>
                        </td>
                        <td>
                            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="bus">
                                <apex:outputText value="{!bus.Business__r.Business_Name__c}" rendered="{!bus.Business__r.Business_Type__c = 'Exporter'}"></apex:outputText>
                            </apex:repeat>
                        </td>
                        <td>
                            <apex:repeat value="{!c.Subject_for_Cases__r}" var="sub">
                                <apex:outputText value="{!sub.Subject_Name__r.Subject_Name__c}" rendered="{!sub.Subject_Name__r.Subject_Type__c = 'Exporter'}"></apex:outputText><br></br>
                            </apex:repeat>
                        </td>
                        <td>
                            <apex:repeat value="{!c.BusinessCasesAssociations__r}" var="businessCaseAssociation">
                                <!-- use the businessMap in the controller to show the business data for this view -->
                                <apex:outputField value="{!businessMap[businessCaseAssociation.Business__c].Name}" />
                                <apex:outputField value="{!businessMap[businessCaseAssociation.Business__c].Business_Type__c}" />
                                <apex:outputField value="{!businessMap[businessCaseAssociation.Business__c].Business_Name__c}" />

                                <!-- or pass the business__c record from the businessMap itself to the component -->
                                <!-- example assumes the component has a parameter on it for 'theBusiness' of type Business__c -->
                                <c:business_shipper_contact_info theBusiness="{!businessMap[businessCaseAssociation.Business__c]}" /><br></br>
                            </apex:repeat>
                        </td>

Update

Just implementing this in your original component would likely solve the issue without my full rewrite of your page controller class.

Your component doesn't need the page controller referenced on it too, doing so causes each one of those components that is repeated in the page to construct one of those page controllers and run its own query for the same data.

You just should pass the data from the page controller that you've already queried into the component using an attribute and then the <apex:outputText /> elements in the component can use that reference to output the text into the page.

Component markup that accepts a Business__c record and references fields on this record. Assuming this component is named business_shipper_contact_info.

<apex:component>
    <apex:attribute name="theBusiness" type="Business__c" description="The business__c record" required="true" />

    <apex:outputText value="{!theBusiness.Street__c}" />&nbsp;
    <apex:outputText value="{!theBusiness.Business_City__c}" />&nbsp;
    <apex:outputText value="{!theBusiness.State_Province__c}" />&nbsp;
    <apex:outputText value="{!theBusiness.Country__c}" />&nbsp;
    <apex:outputText value="{!theBusiness.Zip_Postal_Code__c}" />       
</apex:component>

Markup in your VF page using this <c:business_shipper_contact_info> component. This is also at the end of my modification of your VF markup. c is a reference to a Case__c.

<apex:repeat value="{!c.BusinessCasesAssociations__r}" var="businessCaseAssociation">
    <c:business_shipper_contact_info theBusiness="{!businessMap[businessCaseAssociation.Business__c]}" /><br></br>
</apex:repeat>

If you decided that you wanted to pass a list of business__c records to a component instead of just one, you could do it like this using an array of Business__c records for the type of the attribute and a repeat tag in the component to loop over them:

<apex:component>
    <apex:attribute name="theBusinessList" type="Business__c[]" description="An array of business__c records" required="true" />

    <apex:repeat value="{!theBusinessList}" var="theBusiness">
        <apex:outputText value="{!theBusiness.Street__c}" />&nbsp;
        <apex:outputText value="{!theBusiness.Business_City__c}" />&nbsp;
        <apex:outputText value="{!theBusiness.State_Province__c}" />&nbsp;
        <apex:outputText value="{!theBusiness.Country__c}" />&nbsp;
        <apex:outputText value="{!theBusiness.Zip_Postal_Code__c}" />       
    </apex:repeat>
</apex:component>
  • Hopefully your code will fix the problem but see my answer that illustrates that it may. – Keith C Mar 24 '16 at 9:21
  • @KeithC yeah I'm not sure that it will ultimately fix it. It's certainly another slightly more query-efficient way to implement it. If it's not one itself, maybe it'll lead to the solution. I'm curious now to the difference between the controller as shown and the controller referenced in the page extensions attribute. – Mark Pond Mar 24 '16 at 16:51
  • @MarkPond I am trying to use your code to see if it works and I keep running into issues. I think I got the controller to work but now the VF page won't see the "{!theCases}" variable in the Controller. I get an error: Unknown property 'Case__cStandardController.theCases'. I am new to this so any assistance would be great. It almost sounds like it is not recognizing the Extension in the VF. Thanks. – Nathan Mar 24 '16 at 17:46
  • 2
    @Nathan the issue with the error of {!theCases} if you copied my example exactly is that the list and the map are both private. Changing them both to public should expose them to the page and resolve that error. Updated my example above to reflect this. – Mark Pond Mar 24 '16 at 19:11
  • 1
    Oh, I see why you're hitting the limit. Your component references the page controller too and it's accessing that businesses list too. Each component will execute the query again. Updating the component markup and adding it to my answer. – Mark Pond Mar 25 '16 at 0:52
4

In relation to what is causing the problem, there is the question of whether the getter is called every time it is referenced in the page or not. The documentation says:

It’s a best practice for getter methods to be idempotent, that is, to not have side effects. For example, don’t increment a variable, write a log message, or add a new record to the database. Visualforce doesn’t define the order in which getter methods are called, or how many times they might be called in the course of processing a request. Design your getter methods to produce the same outcome, whether they are called once or multiple times for a single page request.

The right way to code is as described in the emphasised (by me) sentence. But in my experience getters are called once only as illustrated by this example:

public class T {
    public Integer counter {get; set;}
    public String value {
        get {
            counter = counter != null ? counter + 1 : 1;
            return 'value';
        }
        set;
    }
    public Integer[] sequence {
        get {
            return new Integer[] {0, 1, 2, 3, 4, 5, 6, 7};
        }
    }
}

and page:

<apex:page controller="T">
    <apex:repeat value="{!sequence}" var="s">
        seq: <apex:outputText value="{!s}"/>
        value: <apex:outputText value="{!value}"/>
        counter: <apex:outputText value="{!counter}"/>
        <br/>
    </apex:repeat>
</apex:page>

produces this output:

seq:0 value:value counter:1 
seq:1 value:value counter:1 
seq:2 value:value counter:1 
seq:3 value:value counter:1 
seq:4 value:value counter:1 
seq:5 value:value counter:1 
seq:6 value:value counter:1 
seq:7 value:value counter:1 

So it is not certain that caching the results within the controller will fix the problem.

  • Thanks for the insight. Wish what I was trying to do was that simple. – Nathan Mar 25 '16 at 0:03

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.