Friday, October 24, 2014

Share Chatter files across communities... or not

"One version of the truth" is the holy grail in content management. Chatter Files is salesforce.com's solution for allowing users to manage document revisions in Salesforce, while making sure that links to the file always give people the latest version. But with Communities, "one version of the truth" becomes more difficult to achieve.

Take the following scenario:
  1. John Doe collaborates with internal users to create a pitch deck for a new product.
  2. John uploads the file to the Competitive Advantage Chatter group in his org's internal community.
  3. Several iterations later, the deck is ready to be shared in his company's partner community, called AllianceNet.
  4. John uses the Global Header to switch from his org's internal community to the AllianceNet community.
  5. John goes to the All AllianceNet group to share the file, already stored in Chatter, with the group, but... where's the file?



As it stands in Winter '15, files created or uploaded to one community, internal or external, can only be shared within that same community in Chatter. So, to share a file across communities, users effectively have to recreate a duplicate instance of the file by uploading it again as a new file to the new community.

The only way that files can be shared or seen across communities is to create a Salesforce CRM Content library that's shared with users who have access to multiple communities. But even then, users will not be able to attach the file to a Chatter post. They'll be able to find the file in Global Search, and share URL links to the file, but unfortunately "native" Chatter file attachments will not be possible.

If this limitation with file sharing across communities affects or bothers you, please promote the idea, "Sharing Files from Chatter to Communities".

Friday, October 10, 2014

Invalid apex:attribute name values

The apex:attribute component in Visualforce allows developers to pass custom Apex class instances as attributes from the parent component or page to the child component. In this manner, it's possible to pass a page controller itself as an attribute to a component on the page, using a simple self property like the following.

public CustomController getSelf() {
    return this;
}

What the documentation doesn't say is that apparently (at least in Winter '15, API 32.0) there are keywords to avoid when naming your attribute, even though the Visualforce parser will not tell you there's a problem.

Trying to name your attribute "controller" will cause something like the following error to appear when saving a page: Wrong type for attribute <c:buggersitepaypalcheckout controller="{!self}">. Expected BuggerSiteSimpleSelfRegController, found String



Trying to name your attribute "parent" will cause a completely blank error message to appear when saving a page. But it's an error that will prevent you from saving your page, nonetheless.



Do you know any other hidden no-no's with naming apex:attribute elements? Please share so that we can all avoid these frustrating quirks int he future.

Monday, September 22, 2014

Your request cannot be processed at this time. The site administrator has been alerted.

In setting up and testing self-registration for a new community built on Salesforce Communities, you may encounter this confounding error: "Your request cannot be processed at this time. The site administrator has been alerted."

"Alerted" in the above statement refers to an email alert that went out to the site administrator. But who is the "site administrator"? You can find the email address used for this notification by locating the Site Guest User for your community's Force.com site.
  1. Open Setup > Manage Communities
  2. Click Force.com for the community in question
  3. Click Edit
  4. Change Site Contact to the user who should receive notifications when errors arise with self-registration. Make sure the user's email address is valid.


For sandboxes, make sure your Access to Send Email is set to "All email", under Setup > Email Administration > Deliverability. (Thanks Lynnet!)


Below are a few common reasons why you may be encountering the problem:
  • The community is not published. In case you're working with a community that is offline or in Preview status, you need to publish the community before self-registration will work.
  • The Account Owner does not have a User Role assigned. If you're creating a new Account record on the fly, especially in B2C situations, you need to make sure you assign a default account owner that also has a User Role value. Any role will do, and you can use either a workflow rule or Apex to perform the assignment.
  • The site guest user does not have Create and Read permissions on the Account and Contact objects. Edit Public Access Settings for the community's Force.com site to grant these permissions, along with field permissions for any fields that are included on the self-registration form. Note that by default the site's profile will not have these permissions.
  • Self-registration is not enabled for the community. Go to Manage Communities, click Edit and make sure the Login settings show that self-registration is enabled.

For more details on setting up a community for self-registration, please refer to the Getting Started with Communities guide.

Wednesday, August 20, 2014

Close recurring tasks using Apex

At least one developer had reported encountering an error when trying to automate updates to Task records using Apex: System.UnexpectedException: Apex Task trigger cannot handle batch operations on recurring tasks. This error occurs even in simple scenarios, such as simply closing any open tasks on a close opportunity.

While I agree with what I imagine to be general consensus that this error seems crazy, luckily there appears to be a workaround: Update a custom flag using Apex, and then use workflow rules to handle the dirty work of updating restricted standard field(s).

While I've only tested this approach on the scenario below, I think it will be applicable to solving other similar problems with updating Task records using Apex.

Sample solution to close recurring tasks using Apex


The anonymous Apex code below illustrates the solution.


And there's nothing special about the checkbox field, the workflow rule or the field update. The idea is that when the checkbox is checked, the workflow rule fires and performs the field update.


Friday, August 8, 2014

Created By and Last Modified By not set before insert or update

After some frustrating troubleshooting of what I thought would be simple code today, I learned something unexpected: Created By and Last Modified By are not populated or set in the before context of DML operations. This means that before insert, CreatedById, CreatedDate, LastModifiedById and LastModifiedDate are all empty. And before update, LastModifiedById and LastModifiedDate will reflect the previous person to modify the record, not the current user (which would be yourself if you are the one editing the record).

While this was counter-intuitive at first, I came to realize that there's no need to rely on those fields in the context of Apex triggers. All I really need is UserInfo.getUserId() and DateTime.now() to get the time.

Just like that... I learned something new today.

Tuesday, August 5, 2014

Person Accounts ignore Contact workflow rules and triggers

Every once in a while I find myself discussing the pros and cons Person Accounts, and inevitably a question comes up about how Account and Contact workflow rules and triggers are impacted. The vague statement that precipitates the question usually goes something like this, "Turning on Person Accounts creates problems for existing workflow rules and triggers." Today I finally decided to explore the validity of this statement myself, and the results were... well, disappointing.

The good news is that turning on Person Accounts will not break any of your existing functionality regarding Business Accounts and Contacts, as long as your Apex code is not automatically creating Contact records for accounts to emulate a one-to-one Account-Contact model.

The bad news is that none of your Contact workflow rules and triggers will fire for Person Account records. To me, this is a problem and poor design of the Person Accounts feature. Admins should at least be given the option to configure, perhaps via a checkbox, whether Contact workflow rules and triggers will fire for Person Account records. But as it currently stands, all benefits from existing Contact workflows and triggers are lost for person accounts.

If you agree with why the above bad news is bad, please promote this idea, "Person Accounts to work with Contact workflows and triggers." And read on if you want to know how I arrived at the above conclusions, which were tested in an Enterprise Edition org with Person Accounts enabled.

Test Setup (Summer '14)


The tests makes use of the following Text fields, for which history tracking is turned on:

  • Account Trigger Message (Account field)
  • Account Workflow Message (Account field)
  • Contact Trigger Message (Contact field)
  • Contact Workflow Message (Contact field)
To interact with those fields, we'll create two triggers and two workflow rules that simply set values for the implied fields on the Account and Contact object.
  • SetAccountTriggerMessage (Account trigger)
  • Set Account Workflow Message (Account workflow rule)
  • SetContactTriggerMessage (Contact trigger)
  • Set Contact Workflow Message (Contact workflow rule)
Now, with the stage set, let's move on to the tests.

Test 1: Create a person account


What happens when we create a person account?  Account workflow rules and triggers fire, but Contact workflow rules and triggers do not.

Test 2: Update an Account-only field on the person account


What happens when we update the Website field? Account workflow rules and triggers fire, but Contact ones do not.

Test 3: Update a Contact-only field on the person account


What happens when we update the Birthdate field? Oddly enough, Account workflow rules and triggers fire, but Contact ones do not.

Test 4: Update a special Account-Contact field on the person account


Knowing that the Account Name is linked to First Name and Last Name for Person Account records, what workflows and triggers will fire when you edit First Name or Last Name? Once again, Account workflow rules and triggers fire, but Contact ones do not.

Workaround for Contact workflows and triggers


The only supportable way to get Contact workflows and triggers to fire for Person Account records seems to be to recreate those workflows and triggers on the Account object. Whether this workaround is a pro or a con depends on your point of view. Obviously this creates more work and maintenance, but it allows for more granular and logical control over what happens with Contact fields for a person account vs. a regular contact.

Wednesday, July 9, 2014

XML Parsing Error: XML or text declaration not at start of entity

I'm not sure whether it's an XML specification requirement, but it appears that when rendering XML with Salesforce there cannot be any whitespace between the apex:page start tag and the first character.

The following code will work:


But the following code with visually pleasing indention will not:


If there are any unexpected spaces present after the apex:page start tag, you will likely encounter an error: XML Parsing Error: XML or text declaration not at start of entity