четверг, 15 октября 2015 г.

Introducing concat – pretty Apex string builder for Salesforce/Force.com

Concatenating strings in Apex with "+" operator  or String.join() can be full of pain. Unwanted spaces and commas. Empty or null strings. Ugly cascades of checks. Familiar?

Concat provides a solution!

It's key features are:

  • Null- and empty string safe
  • Clear chaining syntax

String result = 
concat.strings('Apex', 'can', 'be').add('less').add('').

Pretty easy, huh?

среда, 14 октября 2015 г.

Force.com Fundamentals 30 Questions Quiz to Prepare Salesforce Certification

Salesforce Certifications are widely recognized qualifications that prove to employers or customers that you are a professional in a specific Salesforce area.

Checking you knowledge of platform basics is necessary before diving into preparation to specific certification. I've created a quiz of 30 questions covering this need. Force.com Fundamentals test checks your knowledge of native functionality of the Force.com platform, including designing and creating Force.com objects, modifying the appearance of the standard Force.com interface, the Force.com security scheme, reporting on your data, using workflows and more. This quiz can be useful for Salesforce developers and administrators starting certification process.

Questions are based on Force.com Platform Fundamentials book. Reading this book is highly recommended before starting the quiz.

Good luck!

вторник, 13 октября 2015 г.

Solution to display Salesforce user profile photos on external Force.com sites without authentication

Displaying Salesforce user profile images on external sites is a wide known problem. Access to User.SmallPhotoURL or User.LargePhotoURL needs authentication and that's the trouble. There are various solutions provided by different Salesforce developers, for example:
  • authorizing via OAuth by attaching "?oauth=[your-token]" to photo url - seriously?.. send valid access token to unauthorized client?
  • saving user photos as custom objects attachments - pretty tricky to implement and really ugly solution.
But there is a simple and 100%-working solution (thanks to Denis from Synebo)!

public String getUserPhotoURL(String UserId) {
    ConnectApi.Photo ph =  ConnectApi.ChatterUsers.getPhoto(null, UserId);
    return ph.fullEmailPhotoUrl;
 Notice, that resulting URL expires 30 days after it was obtained. It doesn't matter if you are using it on dynamic pages (since you are requesting a new URL every time when page is reloaded), but keep it in mind when using URL in some static stuff (emails, static pages, etc).

вторник, 6 октября 2015 г.

TriggerTransaction Apex class for cleaner Salesforce triggers

My newly written Salesforce Apex TriggerTransaction class allows you to accumulate changes made to DB in trigger code to minimize DML requests number. Tastes better with kevinohara80/sfdc-trigger-framework.


You need my xforce utility class to use TriggerTransaction.

Usage example

This example uses kevinohara80/sfdc-trigger-framework.



Create new Apex Trigger named AccountTrigger.apxt with the following code:

trigger AccountTrigger on Account (before insert,
                                   before update,
                                   before delete, 
                                   after insert,
                                   after update,
                                   after delete,
                                   after undelete) {

      new AccountTriggerHandler().run();



Trigger handler class

Create new Apex Class named AccountTriggerHandler.apxc with the following code:

public class AccountTriggerHandler extends TriggerHandler {

    public override void afterInsert() {
        TriggerTransaction transact = new TriggerTransaction 
                new List<String> {'Account', 'Contact', 'Opportunity'});
        for(Account account_i : (List<Account>) Trigger.new) {
            transact.ups('Contact', new Contact(AccountId = account_i.id,
                                                        +' Main Contact'));
        List<Contact> shadowList = transact.shadow([select id, lastName
                                                    from Contact limit 100]);
        X.debug('Shadow contact list', shadowList);