Adding New Fields can break Existing Visualforce Pages
I recently came across an interesting discussion where adding a new field to a Object broke some of the existing code. It’s strange right, mostly removing or renaming fields is risky, as they could break some String expressions or merge fields.
Here is the error in one of the possible forms for “Name” field:
Unknown property ‘VisualforceArrayList.Name’
Error is in expression ‘{!Contact.Location__r.Name}’ in component <apex:page> in page abhinav:contacts
Here is one quick way to end up in this problem:
For keeping stuff simple, I have tried to keep the fixture minimal.
1. Let’s assume we have a custom object called “Location__c”.
2. Create a lookup field on the standard Contact object, it will relate to “Location” custom object and the field API name is “Location”.
3. Here is a simple Visualforce page that uses this field, which has worked fine till now.
<apex:page standardController="Contact" >
{!Contact.Location__r.Name}
</apex:page>
4. Now add a lookup field on Location object, which relates to Contact. Make sure the “Child relationship name” is “Location” not “Locations”, as indicated below:
5. Now revisit the same Visualforce page, you will get the error this time:
Why this happened?
Contact has two relations now with the same name i.e.
First “Location__r” refers to the parent Location record i.e. Location__c record.
Second “Location__r” refers to child relationship location records i.e. List of Location__c records.
This breaks the Visualforce runtime, as the above code maps code is meant to load the parent location’s name from Contact, but it gets a handle to child relationship one i.e. “List of Location__c records”. So as indicated in error, there is no such property called “Name” in ArrayList and it fails at runtime.
Important observations
1. This problem only comes in Visualforce code referring an ambiguous relationship, similar Apex code will work fine, one such sample is shown below
public static Contact loadLastChangedContact () {
Contact con = [Select Name, Location__r.Name from Contact Order By LastModifiedDate DESC LIMIT 1];
System.debug ('Location Name: ' + con.Location__r.Name);
return con;
}
2. The above case applies to Formulas as well, they are not affected by ambiguous fields.
3. This problem could be trapped, if the Visualforce page is saved again, after adding a new field. It gives the same compilation error.
4. This error will not be trapped in “Run All Tests” as it’s not related to Apex, but Visualforce runtime. Even if your test cases are using System.Test.setCurrentPage(‘…’)
, they will not be able to trap this runtime failure. So, be careful when adding fields to existing objects, it is pretty common to see new fields being added to objects, without full testing of existing code.
5. The same problem could come with renaming the fields, which leads to this duplicity in relationship names on a single object.
Credits
Credit goes to Rajendra Ogra for bringing up this discussion and sharing his findings.