I spent an entire day trying to figure out why I got this error in my deployment but could not figure out why. So I hope someone here could shed some light on this.
This is the error I got. I don't think the issue is in the test class itself because It passed when I run in the DEV org.
I have a VF template called like this:
<messaging:emailTemplate subject="Event Confirmation"
recipientType="Contact"
relatedToType="CampaignMember"
renderUsingSystemContextWithoutSharing="True">
<messaging:htmlEmailBody >
<html>
<body style="max-width: 500px; margin: 0 auto">
<!-- Image from Campaign -->
<apex:image url="{!relatedTo.Campaign.Event_Image_URL__c }"
style="max-height: 300px; max-width: 500px; display: block; margin: 0 auto"/>
<!-- Welcome message -->
<h1 style="text-align: center; font-size: 22px; font-weight: bold;">Hello {!relatedTo.Contact.FirstName},</h1>
<h2 style="text-align: center; font-size: 18px;">{!relatedTo.Campaign.Confirmation_Welcome_Message__c}</h2>
<h2 style="text-align: center; font-size: 18px;">
<a href="{!relatedTo.Campaign.Event_Page_URL__c}">{!relatedTo.Campaign.Name}</a>
</h2>
<div style="height: 32px; border-bottom: 1px solid black; margin-bottom: 32px"></div>
<!-- Event details -->
<h3 style="font-size: 16px; font-weight: bold">Event Details</h3>
<p>{!relatedTo.Campaign.Subtitle__c}</p>
<p><span style="font-weight: bold">Start Date and Time:</span>
<c:EventTemplateDateTime campaign_owner_id="{!relatedTo.Campaign.OwnerId}" campaign_id="{!relatedTo.Campaign.Id}" date_time_format=" EEE, MMM d yyyy h:mm a" startOrEnd="start"/>
</p>
<p><span style="font-weight: bold">End Date and Time:</span>
<c:EventTemplateDateTime campaign_owner_id="{!relatedTo.Campaign.OwnerId}" campaign_id="{!relatedTo.Campaign.Id}" date_time_format=" EEE, MMM d yyyy h:mm a" startOrEnd="end"/>
</p>
<!-- Session information -->
<h3 style="font-size: 16px; font-weight: bold">Session Information</h3>
<c:EventConfirmationSessionDetails cpMemberId="{!relatedTo.Id}"/>
<div style="height: 32px; border-bottom: 1px solid black; margin-bottom: 32px"></div>
<!-- Online information -->
<p style="text-align: center; margin: 0px 0px 20px 0px">For more information and to download the session material, please visit the event page by clicking <a href="{!relatedTo.Campaign.Event_Page_URL__c}">here</a>.</p>
<!-- Ending message -->
<p style="text-align: center; margin: 0px"><apex:outputText value="{!relatedTo.Campaign.Confirmation_Ending_Message__c}" escape="false" style="white-space: pre"/></p>
</body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>
This is the component inside the above template, which contains the attribute that caused the error:
<apex:component controller="EventConfirmationController" access="global">
<apex:attribute assignTo="{!campaignMemberId}"
name="cpMemberId" type="String"
access="global"
description="Id of the campaign member that receives the email"/>
<apex:dataTable value="{!Sessions}" var="s">
<apex:column style="padding-right: 8px; width: 150px">
<apex:facet name="header"><span style="font-weight: bold">Session Name</span></apex:facet>
{!s.Name}
</apex:column>
<apex:column style="padding-right: 8px; width: 150px">
<apex:facet name="header"><span style="font-weight: bold">Date</span></apex:facet>
{!s.SessionDate}
</apex:column>
<apex:column style="padding-right: 8px; width: 150px">
<apex:facet name="header"><span style="font-weight: bold">Time</span></apex:facet>
{!s.SessionTime}
</apex:column>
<apex:column style="padding-right: 8px; width: 150px">
<apex:facet name="header"><span style="font-weight: bold">Location</span></apex:facet>
<apex:outputText value="{!s.SessionLocation}" escape="false" />
</apex:column>
</apex:dataTable>
</apex:component>
This is the component's controller:
public with sharing class EventConfirmationController {
public String campaignMemberId;
public List<EventConfirmationHelper.SessionWrapper> Sessions;
public String campaignOwnerId {get;set;}
public String campaignId {get;set;}
public String defined_format {get;set;}
public String FormattedDatetime;
public String startOrEndDate {get; set;}
public EventConfirmationController(){
}
public void setcampaignMemberId(String cpMemberId){
campaignMemberId = cpMemberId;
if (campaignMemberId != null){
Sessions = EventConfirmationHelper.getSessionsDetails(campaignMemberId);
}
}
public String getcampaignMemberId(){
return campaignMemberId;
}
public List<EventConfirmationHelper.SessionWrapper> getSessions() {
return Sessions;
}
// Format event Start Time based on event's owner timezone
public String getFormattedDatetime() {
return EventConfirmationHelper.getFormattedDateTimeHelper(campaignOwnerId, campaignId, startOrEndDate, defined_format);
}
}
As you can see I have set the attribute in the component to be global as required as in SF documentation.
Everything works fine during functional test (campaign member Id passed in the attribute and session records were returned).
So what did I miss? Thanks all.
cpMemberId
attribute, deploy, then put it back in, then deploy again. Occasionally the deployment logic fails to track the dependency chain correctly when multiple components change,