1

First, let me state that all of the following code works except forgetting the error to display on the page and that is a big problem! With that said, I have googled all day and have read at least 25 different posts about having the same problem and have tried several different things in several different places. Please see the bottom of this question for things I have already tried. Here's the code: ********This Code Has Been Edited With The Changes Suggested Through 9/21/2017********

Visualforce page:

<apex:page standardController="Case"  extensions="CaseControllerExt" Title="New Warranty Claim" showHeader="false" id="createNewWarranty" docType="html-5.0">
<script type='text/javascript' src='/canvas/sdk/js/publisher.js'/>
<script>
    function refreshFeed(){
    Sfdc.canvas.publisher.publish({name : 'publisher.refresh', payload : {feed:true}});
    }
</script>
<apex:stylesheet value="{!$Resource.NewWarrantyClaimButtonVFPageCSS}"/>
    <apex:form >
        <apex:pageBlock title="New Warranty Claim" id="viewCreateClaim">
            <apex:outputPanel id="pageMessages">
                <apex:outputText value="This is where error messages should get shown!"></apex:outputText>
                <apex:pageMessages id="showErrors" showDetail="true"/>
            </apex:outputPanel>
            <apex:outputPanel styleClass="explanation" rendered="{!showCreateButtons}">
                <p>
                    <apex:outputText value="These buttons will create a new Warranty Claim if the product has been registered and marked as a faulty unit on the Case."></apex:outputText>
                </p>
                <p>
                    <apex:outputText value="If none of the products that are marked faulty have been registered you will be instructed to create the Warranty Claim manually."></apex:outputText>
                </p>
            </apex:outputPanel>
            <apex:pageBlockButtons id="createButtons" styleclass="displayBlock" rendered="{!showCreateButtons}">
                <apex:actionFunction action="{!unitReplacement}" name="unitReplacement"/>  
                <button type="button" value="unitReplacement" onclick="unitReplacement();">Create Warranty Claim For Unit Replacement</button>
                <apex:actionFunction action="{!partsUnderWarranty}" name="partsUnderWarranty"/> 
                <button type="button" value="partsUnderWarranty" onclick="partsUnderWarranty();">Create Warranty Claim For Parts - Unit Under Warranty</button>
                <apex:actionFunction action="{!partsOutOfWarranty}" name="partsOutOfWarranty"/> 
                <button type="button" value="partsOutOfWarranty" onclick="partsOutOfWarranty();">Create Warranty Claim For Parts - Unit Out of Warranty (90 days for parts and 1 year compressor)</button>
            </apex:pageBlockButtons>


        </apex:pageBlock>
        <apex:pageBlock id="viewClaim" >
            <apex:outputPanel rendered="{!showViewButtons}">
                <apex:outputPanel >
                    <p>
                        <apex:outputText value="To view the claim that was created and finish adding the required information, click the button labled View Warranty Claim."></apex:outputText>
                    </p>
                </apex:outputPanel>
            </apex:outputPanel>
            <apex:pageBlockButtons rendered="{!showViewButtons}">
                <apex:actionFunction action="{!createWarranty}" name="createWarranty" rerender="pageMessages" oncomplete="refreshFeed();"/>  
                <button type="button" value="createWarranty" onclick="createWarranty();">View Warranty Claim</button>
            </apex:pageBlockButtons>
        </apex:pageBlock>
    </apex:form>

Controller:

public with sharing class CaseControllerExt {
private final SObject parent;
public String firstError {get;set;}
public String secondError {get;set;}
public String thirdError {get;set;}
public String fourthError {get;set;}  
public String fifthError {get;set;}
public String lastError {get;set;}
public String unitReplacement {get;set;}
public String partsUnderWarranty {get;set;}
public String partsOutOfWarranty {get;set;}
public String recordTypeToSwitchTo {get;set;}
public Id Id {get;set;}
public Id warrantyClaimId {get;set;}
public Id recordTypeId {get;set;}
public List<Id> warrantyClaimIds {get;set;}
public List<Id> caseIdsAndRecordTypeId = new List<Id>();
public boolean showCreateButtons {get;set;}
public boolean showViewButtons {get;set;}
public Case cs;

public HVAC_Warranty_Claim_Form__c cf;

private ApexPages.StandardController sc;
// List<ApexPages.Message> errorList = new List<ApexPages.Messages>();

public CaseControllerExt(ApexPages.StandardController controller){

    try{
        showViewButtons = false;
        System.debug('$$$$$showViewButtons - ControllerExtension$$$$$' + showViewButtons);
        showCreateButtons = true;
        System.debug('$$$$$showCreateButtons - ControllerExtension$$$$$' + showCreateButtons);
        parent = controller.getRecord();
        System.debug('*****Parent Record*****' + parent);
        cs = new Case();
        cs.AccountId = parent.id;
        System.debug('*****Case Record Id aka cs.AccountId*****' + cs.AccountId);
        System.debug('*****Case Record*****' + cs);

        caseIdsAndRecordTypeId.add(cs.AccountId);
        System.debug('*****caseIdsAndRecordTypeId List*****' + caseIdsAndRecordTypeId);
        // lastError = '';
        System.debug('*****Case Record Id aka cs.AccountId*****' + cs.AccountId);
        System.debug('*****Case Record*****' + cs);
        // System.debug('*****lastError*****' + lastError);
    }catch (Exception ex1){
        ApexPages.addMessages(ex1);
        firstError = ex1.getMessage();
        System.debug('@@@@@firstError@@@@@' + firstError);
    }
}  

public void unitReplacement(){
    try{
        showViewButtons = true;
        System.debug('$$$$$showViewButtons - UnitReplacement$$$$$' + showViewButtons);
        showCreateButtons = false;
        System.debug('$$$$$showCreateButtons - UnitReplacement$$$$$' + showCreateButtons);
        unitReplacement = 'Unit Replacement';
        System.debug('^%^%^%^%^unitReplcmnt^%^%^%^%^' + unitReplacement);
        recordTypeToSwitchTo = unitReplacement;
        System.debug('^%^%^%^%^recordTypeToSwitchTo^%^%^%^%^' + recordTypeToSwitchTo);
        assignRecordType(recordTypeToSwitchTo);
    }catch (Exception ex2){
        ApexPages.addMessages(ex2);
        secondError = ex2.getMessage();
        System.debug('@@@@@secondError@@@@@' + secondError);
    }
}

public void partsUnderWarranty(){
    try{
        showViewButtons = true;
        System.debug('$$$$$showViewButtons - UnderWarranty$$$$$' + showViewButtons);
        showCreateButtons = false;
        System.debug('$$$$$showCreateButtons - UnderWarranty$$$$$' + showCreateButtons);
        partsUnderWarranty = 'Parts - Unit Under Warranty';
        System.debug('^%^%^%^%^partsUnderWarranty^%^%^%^%^' + partsUnderWarranty);
        recordTypeToSwitchTo = partsUnderWarranty;
        System.debug('^%^%^%^%^recordTypeToSwitchTo^%^%^%^%^' + recordTypeToSwitchTo);
        assignRecordType(recordTypeToSwitchTo);
    }catch (Exception ex3){
        ApexPages.addMessages(ex3);
        thirdError = ex3.getMessage();
        System.debug('@@@@@thirdError@@@@@' + thirdError);
    }
}

public void partsOutOfWarranty(){
    try{
        showViewButtons = true;
        System.debug('$$$$$showViewButtons - OutOfWarranty$$$$$' + showViewButtons);
        showCreateButtons = false;
        System.debug('$$$$$showCreateButtons - OutOfWarranty$$$$$' + showCreateButtons);
        partsOutOfWarranty = 'Parts - Unit Out of Warranty (90 days for parts and 1 year compressor)';
        System.debug('^%^%^%^%^partsOutOfWarranty^%^%^%^%^' + partsOutOfWarranty);
        recordTypeToSwitchTo = partsOutOfWarranty;
        System.debug('^%^%^%^%^recordTypeToSwitchTo^%^%^%^%^' + recordTypeToSwitchTo);
        assignRecordType(recordTypeToSwitchTo);
    }catch (Exception ex4){
        ApexPages.addMessages(ex4);
        fourthError = ex4.getMessage();
        System.debug('@@@@@fourthError@@@@@' + fourthError);
    }
}

public PageReference createWarranty(){
        warrantyClaimId = createNewWarranty(warrantyClaimId);
        PageReference claimView = new PageReference('/' + warrantyClaimId);
        System.debug('!!!!!!Page To Redirect To!!!!!' + claimView);
        claimView.setRedirect(true); 
        return claimView;
}

public void assignRecordType(String recordTypeToSwitchTo){
    try{
        recordTypeId = Schema.SObjectType.HVAC_Warranty_Claim_Form__c.getRecordTypeInfosByName().get(recordTypeToSwitchTo).getRecordTypeId();
        System.debug('^%^%^%^%^recordTypeId^%^%^%^%^' + recordTypeId);
        caseIdsAndRecordTypeId.add(recordTypeId);
        System.debug('^%^%^%^%^caseIdsAndRecordTypeId^%^%^%^%^' + caseIdsAndRecordTypeId);
    }catch (Exception ex5){
        ApexPages.addMessages(ex5);
        fifthError = ex5.getMessage();
        System.debug('@@@@@fifthError@@@@@' + fifthError);
    }
}

private Id createNewWarranty(Id warrantyClaimId){
    if(caseIdsAndRecordTypeId.size() != 2){
        ApexPages.Message noFaultyProduct = new ApexPages.message(ApexPages.Severity.FATAL, 'There was an error getting the Case Id! Please close this window, refresh the window your Case is open in and try again. Should you receive this meassage again, please contact your Mitsubishi Electric Representative.');
        ApexPages.addMessage(noFaultyProduct);
        return null;
    }
    warrantyClaimIds = FindIfEnteredFromSAP.wasProductInfoRecordCreatedFromScan(caseIdsAndRecordTypeId);
    if (warrantyClaimIds[0] == null){
        ApexPages.Message noFaultyProduct = new ApexPages.message(ApexPages.Severity.FATAL, 'You have not marked any case products as faulty units! Please close this window and make the necessary change(s).');
        ApexPages.addMessage(noFaultyProduct);
        return null;
    }else{
        warrantyClaimId = warrantyClaimIds[0];
    }

try{
        FeedItem post = new FeedItem();
        post.parentId = ApexPages.currentPage().getParameters().get('id');
        post.Body = 'A new Warranty Claim has been created';
        post.Type = 'LinkPost';
        post.LinkUrl = '/' + warrantyClaimId;
        post.Title = 'The new claim can be found here!';
        insert post;
        System.debug('!!!!!!Chatter Post created!!!!!' + post.LinkUrl);
    } catch(System.Exception ex6){
        lastError = ex6.getMessage();
        System.debug('!!!!!!Chatter Post NOT created!!!!!' + lastError);
    }
    return warrantyClaimId;
}}

Apex Class:

public class FindIfEnteredFromSAP {
// @InvocableMethod(label='Create New Warranty Claim' description='Creates a new Warranty Claim based on information from the Product Information Record')
public static List<String> wasProductInfoRecordCreatedFromScan(List<Id> caseIdsAndRecordTypeId){
    System.debug('!!!!!caseIdsAndRecordTypeId!!!!!' + caseIdsAndRecordTypeId);
    Id caseId = caseIdsAndRecordTypeId[0];
    System.debug('!!!!!caseId!!!!!' + caseId);
    Id recordTypeIdToChangeTo = caseIdsAndRecordTypeId[1];

    // Get list of Case Products that are marked faulty on the case
    List<Case_Product__c> faultyProducts = new List<Case_Product__c>();
    faultyProducts = [SELECT Id FROM Case_Product__c WHERE Case__c =:caseId AND Faulty_Unit__c = True];
    System.debug('!*!*!*!*!*!faultyProducts!*!*!*!*!*!' + faultyProducts);

    // Find out how long the list of faulty products is
    Integer sizeOfFaultyProduct = faultyProducts.size();
    System.debug('!*!*!*!*!*!faultyProducts.size!*!*!*!*!*!' + faultyProducts.size());

    if (sizeOfFaultyProduct == 0){
        ApexPages.Message noFaultyProduct = new ApexPages.message(ApexPages.Severity.FATAL, 'You have not marked any case products as faulty units! Please close this window and make the necessary change(s).');
        ApexPages.addMessage(noFaultyProduct);
        return null;
    }

    // Subtract one since size of lists is not zero based (i will be reused when creating some new counters)
    Integer i = sizeOfFaultyProduct - 1;
    System.debug('!*!*!*!*!*!SizeOf i !*!*!*!*!*!' + i);
    Integer j;
    Integer k;
    Integer l = 0;
    Integer m;

    List<Id> faultyProductId = new List<Id>();
    try{
    // Get each of the faulty case product Id's because until this apex knows them as Case_Product__c objects 
    for (j = i; j > -1; j--){
            faultyProductId.add(faultyProducts[j].id);
            System.debug('!*!*!*!*!*!faultyProductId!*!*!*!*!*!' + faultyProductId);
        }
    }catch(System.Exception e){
        ApexPages.Message noFaultyProduct = new ApexPages.message(ApexPages.Severity.FATAL, 'You have not marked any case products as faulty units! Please close this window and make the necessary change(s).');
        ApexPages.addMessage(noFaultyProduct);
        return null;    
    }
    // Iterate through each faulty product until you find one with a Warranty_Number__c 
    // which indicates it was actually registered by a person, not a scan only. 
    List<Case_Product__c> productInfoList = new List<Case_Product__c>();
    List<Warranty__c> productToTest = new List<Warranty__c>();
    List<String> warrantyNumber = new List<String>();
    List<Id> productInfoId = new List<Id>();
    Integer sizeOfProductToTest;
    Integer sizeOfProductInfoId;
    Integer sizeOfProductInfoList;
    Integer n;
for (k = i; k > -1; k--){
            System.debug('!*!*!*!*!*!k!*!*!*!*!*!' + k);

            // Get a list of Product_Registration__c's from each Case_Product that is marked faulty
            productInfoList.add([SELECT Product_Registration__c FROM Case_Product__c WHERE Id = :faultyProductId[k]]);
            sizeOfProductInfoList = productInfoList.size();
            System.debug('!*!*!*!*!*!productInfoList.size!*!*!*!*!*!' + productInfoList.size());
            System.debug('!*!*!*!*!*!productInfoList!*!*!*!*!*!' + productInfoList);
        }

    // Put the Id's from the Product_Registration's into a list
    for (Case_Product__c cp : productInfoList)
    {
        productInfoId.add(cp.Product_Registration__c);
        System.debug('!*!*!*!*!*!productInfoId!*!*!*!*!*!' + productInfoId);
    }

    n = sizeOfProductInfoList - 1;
    System.debug('#####sizeOfProductInfoList#####' + sizeOfProductInfoList);
    System.debug('#####n#####' + n);
    for (m = n; m > -1; m--){
        // Get the Warranty_Number's from each faulty product Id
        productToTest.add([SELECT warranty_number__c FROM Warranty__c WHERE Id =:productInfoID[m]]);
        System.debug('!*!*!*!*!*!productToTest!*!*!*!*!*!' + productToTest);
    }

    // put those warranty numbers into a string list since apex considers them to be warranty__c objects currently           
    for (Warranty__c ptt : productToTest)
    {
        warrantyNumber.add(ptt.warranty_number__c);
        System.debug('!*!*!*!*!*!warrantyNumber!*!*!*!*!*!' + warrantyNumber);
    }

    sizeOfProductToTest = warrantyNumber.size();
    System.debug('!*!*!*!*!*!warrantyNumber.size!*!*!*!*!*!' + warrantyNumber.size());

    sizeOfProductInfoId = productInfoId.size();
    System.debug('!*!*!*!*!*!productInfoId.size!*!*!*!*!*!' + productInfoId.size());

    List<Id> warrantyClaimIds = new List<Id>();        
    List<Id> productInfoIds = new List<Id>();
    for (Case_Product__c cp : productInfoList)
    {
        productInfoIds.add(cp.Product_Registration__c);
        System.debug('!*!*!*!*!*!productInfoIds!*!*!*!*!*!' + productInfoIds);
    }
    List<String> registeredProducts = new List<String>();

    // Find out if the warrantyNumber list is empty and if the number . If it isn't, 
    If (sizeOfProductToTest != 0 && sizeOfProductToTest == sizeOfProductInfoId){
        for (l = 0; l <= i; l++){
            if (warrantyNumber[l] != null){
                registeredProducts.add(String.valueOf(productInfoId[l]));
                System.debug('!*!*!*!*!*!productInfoList!*!*!*!*!*!' + registeredProducts);
                warrantyClaimIds = getRegistrationInfoFromProductInfo.getRegistrationInfo(registeredProducts, productInfoIds, caseId, recordTypeIdToChangeTo);
                break;
            }
        }
    }
    return warrantyClaimIds;
}}

Here is the end of the second debug log from clicking the button on the VF page (Code no longer calls my apex class):

14:20:17.0 (21496393)|USER_DEBUG|[121]|DEBUG|^%^%^%^%^caseIdsAndRecordTypeId^%^%^%^%^(500e000000AwKVoAAN, 01231000000y0SAAAY) 14:20:17.0 (21506080)|SYSTEM_METHOD_EXIT|[121]|System.debug(ANY) 14:20:17.0 (21519425)|METHOD_EXIT|[82]|01pe0000000F7Px|CaseControllerExt.assignRecordType(String) 14:20:17.0 (21525737)|SYSTEM_MODE_EXIT|false 14:20:17.0 (21553866)|VF_APEX_CALL_END|CaseControllerExt invoke(partsUnderWarranty) 14:20:17.24 (24626500)|VF_APEX_CALL_START|[EXTERNAL]|/apexpage/pagemessagescomponentcontroller.apex set(conEscape,null) 14:20:17.24 (24646758)|SYSTEM_MODE_ENTER|true 14:20:17.24 (24657778)|VF_APEX_CALL_START|[EXTERNAL]|PageMessagesComponentController set(conEscape,null) 14:20:17.24 (24679474)|VF_APEX_CALL_START|[EXTERNAL]|PageMessagesComponentController invoke(setconEscape) 14:20:17.24 (24709905)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8 14:20:17.24 (24717301)|VARIABLE_SCOPE_BEGIN|[88]|this|ApexPage.PageMessagesComponentController|true|false 14:20:17.24 (24740904)|VARIABLE_ASSIGNMENT|[88]|this|{}|0x7a6c3d5a 14:20:17.24 (24749221)|VARIABLE_SCOPE_BEGIN|[88]|escape|Boolean|false|false 14:20:17.24 (24757068)|VARIABLE_ASSIGNMENT|[88]|escape|null 14:20:17.24 (24853508)|VF_APEX_CALL_START|[EXTERNAL]|/apexpage/pagemessagescomponentcontroller.apex get(severities) 14:20:17.24 (24869071)|SYSTEM_MODE_ENTER|true 14:20:17.24 (24880351)|VF_APEX_CALL_START|[EXTERNAL]|PageMessagesComponentController invoke(getseverities) 14:20:17.24 (24896439)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8 14:20:17.24 (24902104)|VARIABLE_SCOPE_BEGIN|[2]|this|ApexPage.PageMessagesComponentController|true|false 14:20:17.24 (24919846)|VARIABLE_ASSIGNMENT|[2]|this|{}|0x7a6c3d5a 14:20:17.0 (25250803)|VF_APEX_CALL_START|[EXTERNAL]|01pe0000000F7Px|CaseControllerExt get(showCreateButtons) 14:20:17.0 (25262913)|SYSTEM_MODE_ENTER|true 14:20:17.0 (25270248)|VF_APEX_CALL_START|[EXTERNAL]|01pe0000000F7Px|showCreateButtons 14:20:17.0 (25281553)|VF_APEX_CALL_END|showCreateButtons 14:20:17.0 (25294642)|VF_APEX_CALL_END|CaseControllerExt get(showCreateButtons) 14:20:17.0 (25362881)|VF_APEX_CALL_START|[EXTERNAL]|01pe0000000F7Px|CaseControllerExt get(showViewButtons) 14:20:17.0 (25371440)|SYSTEM_MODE_ENTER|true 14:20:17.0 (25377438)|VF_APEX_CALL_START|[EXTERNAL]|01pe0000000F7Px|showViewButtons 14:20:17.0 (25385956)|VF_APEX_CALL_END|showViewButtons 14:20:17.0 (25396748)|VF_APEX_CALL_END|CaseControllerExt get(showViewButtons) 14:20:17.27 (27544259)|VF_APEX_CALL_START|[EXTERNAL]|/apexpage/pagemessagescomponentcontroller.apex set(conEscape,null) 14:20:17.27 (27560831)|SYSTEM_MODE_ENTER|true 14:20:17.27 (27575324)|VF_APEX_CALL_START|[EXTERNAL]|PageMessagesComponentController set(conEscape,null) 14:20:17.27 (27593095)|VF_APEX_CALL_START|[EXTERNAL]|PageMessagesComponentController invoke(setconEscape) 14:20:17.27 (27611632)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8 14:20:17.27 (27618698)|VARIABLE_SCOPE_BEGIN|[88]|this|ApexPage.PageMessagesComponentController|true|false 14:20:17.27 (27640289)|VARIABLE_ASSIGNMENT|[88]|this|{}|0x7a6c3d5a 14:20:17.27 (27651257)|VARIABLE_SCOPE_BEGIN|[88]|escape|Boolean|false|false 14:20:17.27 (27658760)|VARIABLE_ASSIGNMENT|[88]|escape|null 14:20:17.27 (27762807)|VF_APEX_CALL_START|[EXTERNAL]|/apexpage/pagemessagescomponentcontroller.apex get(severities) 14:20:17.27 (27775727)|SYSTEM_MODE_ENTER|true 14:20:17.27 (27788356)|VF_APEX_CALL_START|[EXTERNAL]|PageMessagesComponentController invoke(getseverities) 14:20:17.27 (27807326)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8 14:20:17.27 (27812480)|VARIABLE_SCOPE_BEGIN|[2]|this|ApexPage.PageMessagesComponentController|true|false

I have tried the following:

  1. I have put the error handling in both a if statement as well as a try/catch.
  2. I have used <apex:pageMessages/> as well as <apex:pageMessages></apex:pageMessages>
  3. I have put the apex:pageMessages as a direct child of the form as well as the page block.
  4. I have put the
  5. I have tried to rerender them from the three buttons (unitReplacement, partsUnderWarranty, and partsOutOfWarranty) where the error would be called from.
  6. I have tried to rerender the outputpanel that I wrapped them in. 6. When I do either #5 or #6 the my apex class does not get called, which I think is the problem, but I don't know how to fix it.
  7. My fourth button in the second page block is not part of this problem, but I would like to know if rerender="out" is what's making the page a pop-out because I can't find any documentation that indicates that's a possible value.

Pictures of initial VF page and after you click one of the three buttons

  • You should change your rerender attribute on your <apex:actionFunction> tag to "showErrors" instead of "out". It should match the id attribute of the Visualforce tag you wish to rerender. – Adrian Larson Sep 15 '17 at 23:05
  • 1
    Your VF controller is calling an invocable method that in turn is adding to ApexPages.Message list. Invocable methods shouldn't be using ApexPages as they can be called from non-VF contexts such as ProcessBuilder – cropredy Sep 15 '17 at 23:45
  • @MarkPond Thank you for editing my post to be more readable, but could you tell me what you did to make it that way? I would prefer to post it that way the first time! – AstroLovesCodey Sep 16 '17 at 3:16
  • @AdrianLarson I just got home and will try your and Cropredy's suggestions ASAP! Thanks for your help! Adrian, could you tell me where I can find some sort of documentation for render and rerender that explains more about other options than booleans and objects? If you #7 on my 'I tried this' list, I mentioned my confusion about this. – AstroLovesCodey Sep 16 '17 at 3:23
  • @Cropredy Thank you for the info. I had read somewhere that to call apex from a VF page I had to add that. Is their a page you can point me to that more clearly explains what you mean by invocable methods adding to my apexPages Message and maybe more about invocable methods in general? – AstroLovesCodey Sep 16 '17 at 3:27
2

First problem: this return statement is outside of the if scope braces and this code will always return null. Based on your other code, you intended the return to be inside the braces.

if (sizeOfFaultyProduct == 0){
    ApexPages.Message noFaultyProduct = new ApexPages.message(ApexPages.Severity.FATAL, 'You have not marked any case products as faulty units! Please close this window and make the necessary change(s).');
    ApexPages.addMessage(noFaultyProduct);
}return null;

Second problem: the reason you are not seeing the page messages is because your code is throwing an exception which you're not handling and that behavior trumps all others. It is occurring here:

private Id createNewWarranty(Id warrantyClaimId){
    warrantyClaimIds = FindIfEnteredFromSAP.wasProductInfoRecordCreatedFromScan(caseIdsAndRecordTypeId);
    warrantyClaimId = warrantyClaimIds[0]; // exception thrown here

warrantyClaimIds is null in this context and warrantyClaimIds[0] is trying to get index value 0 from null and an exception is thrown.


Determining what's happening looks daunting but you can see the system popping items from the call stack as it unwinds itself from the place where the exception is being thrown.

  • 16:10:35.0 (29750931)|SYSTEM_METHOD_EXIT|[94]|CaseControllerExt.__sfdc_warrantyClaimIds()

This ^^ is the exit from the getter property within warrantyClaimIds which you reference on line 94 of your page controller class

  • 16:10:35.0 (29814745)|METHOD_EXIT|[78]|01pe0000000F7Px|CaseControllerExt.createNewWarranty(Id)

This ^^ is the exit from the createNewWarranty method

  • 16:10:35.0 (29890098)|FATAL_ERROR|System.NullPointerException: Attempt to de-reference a null object

So, an exception was thrown immediately after executing the getter on line 94, and that exception went unhandled. Even though (as you demonstrated) the page messages collection has your error stuff in it - you'll never see it when an exception is thrown and the exception isn't handled correctly.

You should check for null before calling [0] here: warrantyClaimId = warrantyClaimIds[0]; or you could wrap this code in the try/catch or implement something else in your code ensure you don't ever get a null value for this List.


From the discussion in comments:

The absolute, most generic, exception handling you could implement in the page controller. Wrap each method in a try/catch and in the catch block, output the exception details to the pagemessages collection to be shown onscreen. It's not pretty, but the code will execute in most cases and if there's a problem it'll be shown to the user.

public with sharing class CaseControllerExt {
    private final SObject parent;
    public String lastError {get;set;}
    public String unitReplacement {get;set;}
    public String partsUnderWarranty {get;set;}
    public String partsOutOfWarranty {get;set;}
    public String recordTypeToSwitchTo {get;set;}
    public Id Id {get;set;}
    public Id warrantyClaimId {get;set;}
    public Id recordTypeId {get;set;}
    public List<Id> warrantyClaimIds {get;set;}
    public List<Id> caseIdsAndRecordTypeId = new List<Id>();
    public boolean showCreateButtons {get;set;}
    public boolean showViewButtons {get;set;}
    public Case cs;

    public HVAC_Warranty_Claim_Form__c cf;

    private ApexPages.StandardController sc;

    public CaseControllerExt(ApexPages.StandardController controller) {

        try { // generic try around everything, just to make sure nothing goes uncaught

            showViewButtons = false;
            showCreateButtons = true;
            parent = controller.getRecord();
            cs = new Case();
            cs.AccountId = parent.id;

            caseIdsAndRecordTypeId.add(cs.AccountId);
            lastError = '';

        } catch (Exception ex) {
            // never swallow an exception by leaving this empty or only
            // write out the exception message to the debug log
            ApexPages.addMessages(ex);
        }
    }  

    public void unitReplacement(){
        try { // generic try around everything, just to make sure nothing goes uncaught

            showViewButtons = true;
            showCreateButtons = false;
            unitReplacement = 'Unit Replacement';
            recordTypeToSwitchTo = unitReplacement;
            assignRecordType(recordTypeToSwitchTo);   

        } catch (Exception ex) {
            // never swallow an exception by leaving this empty or only
            // write out the exception message to the debug log
            ApexPages.addMessages(ex);
        }
    }

    public void partsUnderWarranty(){

        try { // generic try around everything, just to make sure nothing goes uncaught

            showViewButtons = true;
    <snip/>
  • #4 should have said that I had tried return null; both inside and outside (as I had seen on it both ways on other answered questions) the code block, but somehow that got erased and I didn't realize it when I posted. HOWEVER, for others reading this later, @MarkPond did a very nice thing editing this so it was easier to read, but he also move the return null statement so you can't see what was originally posted. I don't have enough characters left to ask you to verify your last comment about the exception being thrown in the wrong place, so please see my next comment. – AstroLovesCodey Sep 16 '17 at 4:32
  • The exception being thrown elsewhere makes sense as to why I would not see a message, but I am trying to wrap my head around why. Please tell me if this makes sense: Even though I am checking for the error on the class that's creating the error, the value is still thrown back to the controller even though none of the other 7 classes that are called after this (last of which is supposed to return the warrantyClaimIds list) are being executed. If that is correct, is there somewhere I can read more about why that happens? – AstroLovesCodey Sep 16 '17 at 4:36
  • @LHYWebDesigner The link above my avatar at the bottom of your question which currently says edited 6 hours ago will show you everyone's edits to your question. I didn't modify any of your code while editing. Feel free to modify the question to be accurate. – Mark Pond Sep 16 '17 at 5:57
  • An unhandled exception stops everything. Any stuff which took place during the transaction before the exception was thrown are discarded / dropped / ignored when an exception goes unhandled. – Mark Pond Sep 16 '17 at 6:12
  • I'm sorry, I didn't realize everyone could click on a link to see the edits. On the regular stackexchange site I never had anyone edit my posts before. I am glad everyone can see the original. – AstroLovesCodey Sep 16 '17 at 6:14
0

Your code seems to be a bit complicated to understand but here are my suggestions:

  1. When you are using actionSupport, you should reRender the areas where you have to refresh, which should also include apex:pageMessage.
  2. Its not good to have multiple try catch blocks. Ensure you cover the entire code in one try catch block.
  3. Now suppose there is a scenario where you are calling another method from another class on your controller. Then you should maintain try catch block on your controller rather than at apex class.
  4. If your method is returning any value, mention return null at catch block.This will help you to rerender the page to display messages.

Please let me know if you need sample code for your help.

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.