1

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.

enter image description here

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.

4
  • Try temporarily commenting out the 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,
    – Keith C
    Commented Sep 6, 2020 at 9:01
  • It seems strange, because the error seems like compilation issue, but it failed inside the test class. Possible it 1 of the cases where SF process builder/flow failed but does not provide clear error message. If the failure indeed during the test you can review the debug log of the deployment and might find there better error message.
    – Liron C
    Commented Sep 6, 2020 at 10:13
  • Hi @KeithC, thanks for your comment, I tried this and the validation passed if the attribute is removed. It failed when I put it back. Commented Sep 7, 2020 at 5:04
  • Hi @LironC, I check the debug and got the same error, but the Operation column showed "<empty>" so I guess the issue is nothing gets passed in the attribute. Thinking of setting a default value, but not sure what yet. Thanks for your help. Commented Sep 7, 2020 at 5:06

2 Answers 2

1

Salesforce released workaround is to split the deployment into two:

  • First deployment contains Apex classes and Visualforce pages
  • Second deployment contains the Visualforce components

As mentioned here. This worked for me.

1
  • 1
    Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.
    – identigral
    Commented May 17, 2023 at 16:16
0

This was resolved by adding a default value for the VF component's attribute.

<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" default=""/>

        <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>

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .