The Silver Lining

Lessons & Learnings from a salesforce certified technical architect.

Developing Chrome Extensions for Salesforce

with 5 comments

Get off my case!Chrome extensions are awesome, they provide amazing convenience that is limited only by your imagination. There are some amazing Chrome Extensions for Salesforce already, some of my favourites being:

As a great fan of JavaScript I’ve always wanted to create a Chrome Extension for Salesforce and I’ve finally gotten around to it. The hardest part was figuring out what context the JS executes in (e.g. in the current tabs context, or in some separate context). Let me step through the code to show you how it’s done.

Chrome Extension Structure

A Chrome Extension is made up of a JavaScript, HTML, images and JSON. At its core is a manifest file which contains the metadata describing your application in JSON. There is a lot of documentation about the structure of this file but some of the key elements are shown below.

{
  "name": "Get off my case!",
  "version": "0.8.1",
  "description": "Presents a notification above the favicon with the number of cases assigned to the current user.",
  "manifest_version": 2,
  "icons" : {
               "16": "img/icons/16.png",
               "48": "img/icons/48.png",
               "128": "img/icons/128.png"
             },
  "permissions": [ "tabs", "https://*.force.com/*", "https://*.salesforce.com/*"],
  "update_url": "https://clients2.google.com/service/update2/crx",
  "author": "Wesley Nolte",
  "browser_action": {
     "default_icon": "img/tquila_lozenge.png"
  },
  "content_scripts": [ {
     "js": [  "js/jquery.js",
              "js/forcetk.js",
              "js/tinycon.js",
              "js/contentscript.js" ],
     "matches": [ "https://*.salesforce.com/*", "https://*.force.com/*" ]
  }]
}

This file references all external resources (JavaScript, images etc.), the important parts here being the JavaScript i.e. jquery.js, forcetk.js, tinycon.js and contentscript.js. In short these files represent:

  • jquery.js – the jQuery library
  • forcetk.js – the JavaScript wrapper for the Salesforce.com REST API, but with one modification i.e. the ability to fetch info about the current user
  • tinycon.js – a small library used to create the notification on the tab
  • contentscript.js – the JavaScript file that brings them all together

The JavaScript

The first 3 JavaScript files are libraries that great, but aren’t particularly interesting in the context of this tutorial. The last file is where the magic happens, the code is listed below.

/* Get the cookie values om nom nom */
function getValueFromCookie(b) {
    var a, c, d, e = document.cookie.split(";");
    for (a = 0; a < e.length; a++)
        if (c = e[a].substr(0, e[a].indexOf("=")), d = e[a].substr(e[a].indexOf("=") + 1), c = c.replace(/^\s+|\s+$/g, ""), c == b) return unescape(d)
}

/* Encapsulating code instead of just letting it lay about */
function init() {
	// Get an instance of the REST API client and set the session ID
	var client = new forcetk.Client();
	client.setSessionToken(getValueFromCookie("sid"));

	// Retrieve the data representing the current user
	client.currentUser(function(response){
		var user = response;

		// Find cases that belong to the current user
		client.query("SELECT COUNT() FROM Case WHERE ownerId = '{0}'".replace("{0}",user.id), function(response){
			Tinycon.setBubble(response.totalSize);
		});
	});
}

init();

In short the code gets the session ID from the user’s cookie (the extension works in the context of the current user session for that tab) and uses that to call in using the REST API. Pretty easy huh?

Sourcecode and Extension Install

The sourcecode is on github if you want to experiment with it, and if you’d like to see it in action you can install it from the Chrome Web Store.

Written by Wes

September 14, 2013 at 1:26 pm

Salesforce: Files vs CRM Content vs Knowledge vs Documents vs Attachments

leave a comment »

The MatrixChoosing the right file or document management system on- (or off-) platform can be a difficult decision, and one of those things that’s difficult to change once implemented so it’s important to make the right choice up front.

Salesforce.com has a number of content and document solutions (and more on the way) and the options when given a set of decision points aren’t always clear. To this end I’ve created a matrix comparing the on-platform systems which should make that decision easier. It’s based on the official documentation but add in a few other key decision points (please don’t sue me Salesforce, I’m just a lowly a certified technical architect!).

If I’ve got anything wrong, or left something out please let me know.

Written by Wes

August 29, 2013 at 7:05 pm

Salesforce User License Feature Matrix

with 4 comments

Understanding Salesforce licensing is incredibly important for all areas of a business buying salesforce and implementation projects. Common questions are:

  • What licenses are available?
  • How much do they cost?
  • Which license types support my intended solution?
  • What are the limitations?
  • How are they “consumed”?

As part of my Salesforce TA Certification I created a matrix that compares all current license types making it easy to learn about licenses and make the licensing decision a bit easier. The matrix isn’t comprehensive but instead tries to balance ease-of-use whilst providing the most important decision points.

Let me know if I missed anything important!

References

Written by Wes

August 10, 2013 at 12:25 pm

Posted in SalesForce

Tagged with ,

Salesforce Certified Technical Architect

with 12 comments

Fall seven times, stand up eight.

- Japanese proverb

Finally, I have this certification. This has been a journey for me, and taken much longer than I anticipated. I did fail the first attempt, but was given a retry (make-up exam) in the sections that I’d failed. I subsequently failed that too. My second, full attempt saw me pass, and in fact I found it quite easy so let me help you learn from my mistakes.

Attempt 1

Late last year I booked in my board review exam. I’m not going to go into the detail of what the board exam entails it’s because this has been discussed in detail here, here and here. I spent a lot of time preparing, and had some ad hoc coaching from the UK SFDC certification team but in the end the hypothetical exam destroyed me. Here’s why:

  • I’d been developing apps for nearly a year and was rusty with regards to various features of the platform used heavily in projects e.g. sharing, roles, content, knowledge
  • I missed the “formal coaching” that SFDC offers for those that pass the board exam, and thought I wouldn’t need it

Together these two things meant that my approach to the hypothetical, and my real-world experience were weak. I knew I’d failed 2 hours into the 4 hour board. Luckily (I suppose) I did very well in the other areas, and my case study was rock-solid so I was given a “make up” exam (2 months later) in my weakest areas.

Attempt 1.1

At this point I’d been back into consulting and oiled my rusty hinges. I also brushed up on any areas of weakness and felt quite prepared. However, the destruction this time around was even worse, I knew I’d failed in the first hour! The reasons here were:

  • I felt the hypothetical here was much more difficult
  • I focussed too much on creating the presentation, and too little on understanding the question
  • I panicked and solved problems that didn’t exist

Attempt 2

Six months after my original attempt I was back in the swing of consulting, working in every role imaginable from sales through to QA and release management. I’d also gone through the “Seed the Partner” official coaching. I honed my approach to the hypothetical and brushed up on Summer 13. And I passed. And it wasn’t that difficult, here’s why:

  • I’d gone through the official coaching with SFDC
  • I’d known the theory all along, but also had the opportunity to flex the old consulting muscles
  • I convinced myself not to panic
  • I read every word of the hypothetical at least twice, focussing on understanding instead of focussing on creating the presentation
  • I drew. I’m not very comfortable with Powerpoint as an architecting tool but for some reason felt compelled to use it in my hypothetical previously. This time around I did what I was comfortable with, telling a story backed by several diagrams drawn in front of the judges as I presented.

I’ve also developed several assets that helped me to study and will be sharing them in a series of posts in the coming weeks.

- Wes Nolte, Force.com MVP, Certified SFDC TA, BBQ Master

Written by Wes

July 24, 2013 at 9:34 pm

Salesforce: Sharing Cheat Sheet

with 4 comments

Sharing is caring.

Sharing is complex, but necessarily so. It gives you incredibly fine-grained control over data access through it’s flexibility but requires quite a deep understanding to do it properly.

There are great articles out there that describe sharing in detail e.g.

Force.com object and record level security

An Overview of Force.com Security

I don’t want to recreate what’s in those articles, instead I’m providing a short, sharp cheat sheet of the major topics you need to understand. So without further ado…

Sharing Cheat Sheet

Sharing Metadata Records

  • “Object[Share]” for standard objects
  • “Object[__Share]” for custom objects
  • Fields: access level, record ID, user or group ID
  • Share records are not created for for OWDs, role hierchies or the “View All” or “Modify All” permissions

Implicit Sharing

  • For Accounts, Contacts, Cases and Opportunities only.
  • A platform feature, cannot be disabled.
  • Access to a parent account—If you have access to a child contact, case or opportunity record of an account, you have implicit Read Only access on that account.
  • Access to child entities—If you have access to a parent account, you may have access to the associated contact, case or opportunity child entities. Access is configure per child object when creating a new role.

Organisation-Wide Defaults (OWD)

  • All standard objects use sharing access through hierarchies and this cannot be disabled
  • Public (Read or R/W) can be seen by all users (including portal)
  • Can’t be changed for contacts if person accounts are enabled

No Relationship

  • All options are available

Master Detail

  • Child objects have their sharing access level and ownership dictated by their parent. This also stands for any grandchildren. The parents value for “Grant access through hierarchies” is also inherited.
  • Child objects don’t have a share-record of their own and will be shared along with the master record.
  • In fact you cannot even define sharing rules from the object detail-page.

Lookup

  • Child objects can have their own sharing access level and ownership. Sharing access through hierarchies can also be disabled.

Manual Sharing

  • Removed when owner changes
  • Removed when access via OWD becomes at least as permissive as the share
  • Private Contacts (those without an Account) cannot be shared manually

Apex Managed Sharing

  • Can be used for Manual Sharing although it isn’t called Apex Managed Sharing in this context
  • Using Apex to share Standard Objects is always considered Manual Sharing i.e. Apex Managed Sharing is only really a feature for Custom Objects
  • Maintained across ownership changes
  • Requires “Modify All” permission

Recalculation

  • Need to create a class that implements the Database.Batchable interface
  • The recalcuation is run when the OWD for the object changes
  • The OWD for the object in question must not be the most premissive access level

Choosing the Right Share Type

“Traditional” / Ownership-based Sharing Rules

  • You want to share the records that a user, group, queue or role own with another user, group or role (includes portal users with roles).

Criteria-based Sharing Rules

  • You want to share records based on values of a specific field or fields with another user, group or role (includes portal users with roles).

Apex Managed Sharing Rules

  • Your sharing requirements are batshit cray-cray. Examples include:
    • Sharing multiple records at once
    • Sharing records on object A based on criteria being met on object B
    • Criteria-based sharing using a field not supported by “Criteria-based Sharing”

Manual Sharing Rules

  • The record owner, or someone with modify all permission, wants to share an individual record with another user, group or role (includes portal users with roles)

Share Groups

  • You want to share records owned by HVP users with internal users, groups or roles (includes portals users with roles)

Sharing Sets

  • You want to “share” records with HVP users. These records need to fulfill the following criteria:
    • Objects has an organization-wide sharing setting different from Public Read/Write
    • Objects is available for Customer Portal
    • Custom object has a lookup field to account or contact

Portals

High Volume Portals (Service Cloud Portals)

  • Include High Volume Customer Portal and Authenticated Website profiles
  • They have no roles and can’t participate in “regular” sharing rules
  • You can share their data with internal users through Share Groups
  • You can share object records where the object is a child record of the HVP user’s contact or account. This is done with Sharing Sets.
  • They can also access records that are:
    • Available for portal, and
    • (Public R/RW OWD, or
    • (Private OWD, and
    • They own the record))
  • They can access a record if they have access to that record’s parent and the OWD is set to “Controlled by parent”
  • Cases cannot be transferred from non-HVP to HVP users

other portals

  • Have a role hierarchy at most 3 levels deep and can participate in regular sharing
    • Person accounts only have a single role
    • Business accounts can have 1 – 3 roles.

Large Data Volumes

  • Defer sharing settings (enabled by logging a case) and group calculation on large data loads and modifications

If you’ve got any other items you think should be in this list, let me know in the comments. Peas oat.

Written by Wes

February 20, 2013 at 12:33 pm

Salesforce: Insufficient privileges when trying to access Activity Settings

with one comment

This strange issue blocked access to certain areas of the setup menu in my production Org, and I couldn’t find a comprehensive solution so here we are.

The problem is documented most comprehensively here with problem statement as:

If you choose to show a custom logo in meeting requests, if the admin who specifies the logo specifies a document that other admins cannot access, then other admins will be locked out of the entire activity settings page.

If the file was created in the last six months you can find out which fart-face did this and have a quick chat with them. However, if the change was made more than 6 months ago you’re in a bit of a sticky situation.

The advice of the aforementioned document is to contact salesforce.com support and ask them to let you know who owns the file. However, you can do this yourself using Workbench.

First log in and then click Workbench > Settings and make sure that “Allows SOQL Parent Relationship Queries” is selected. Then click on Queries > SOQL Query.

SELECT Name, ContentType,Description,folder.name,author.name FROM Document WHERE folderId IN ('USER_ID1', 'USER_ID2', 'etc.')

This query will fetch all the Document records in the relevant users’ private folders. You’re looking for a ContentType that is an image, and hopefully the document name or description will help you further narrow the culprits down. The last step is to email all those people (or get log in access) and get them to check their Documents!

Good luck.

Written by Wes

February 4, 2013 at 6:09 pm

Salesforce JavaScript Remoting: Using Apex and JavaScript objects to pass data from client- to server-side and vice versa

with 13 comments

I’ve spoken about how to do this at a high-level during Cloudstock London and there are hints at how it can be done but no formal documentation that I’ve found, so here we are :)

Quite simply JavaScript Remoting will transform Apex objects and classes (or collections of these types) into JavaScript objects for you. The opposite is true too but there are some rules you need to observe.

Apex Types to JavaScript Equivalents

This is the easier of the type conversions in that you don’t have to really do anything to make it happen. The code below uses a custom class that I’ve defined but you can do the same with any sObject too. Let’s have a look at the code.

The Controller

public with sharing class RemotingObjectsController {

    /* The remoting method simply instantiates a two custom types, puts
       them into a list and then returns them. */
    @RemoteAction
    public static List<CustomClass> getClassInstances(){
        List<CustomClass> classes = new List<CustomClass>();

        CustomClass me = new CustomClass('Wes');
        CustomClass you = new CustomClass('Champ');

        classes.add(me);
        classes.add(you);

        return classes;
    }

    /* My custom type */
    public class CustomClass{
        public String firstName{get;set;}

        CustomClass(String firstName){
            this.firstName = firstName;
        }
    }
}

The Visualforce

<apex:page controller="RemotingObjectsController">
  <script>
      // Will hold our converted Apex data structures
      var classInstances;

      Visualforce.remoting.Manager.invokeAction(
        '{!$RemoteAction.RemotingObjectsController.getClassInstances}',
        function(result, event) {
          // Put the results into a var for pedantries sake
          classInstances = result;

          console.log(classInstances);

          // Assign the first element of the array to a local var
          var me = classInstances[0];

          // And now we can use the var in the "normal" JS way
          var myName = me.firstName;
          console.log(myName);
        });
  </script>
</apex:page>

The Output

Console output from the JS code.

JavaScript Types to Apex Equivalents

This is a little tricker, especially when it comes to sObjects. Note that the approach below works for classes and sObjects too.

The Visualforce Page

<apex:page controller="RemotingObjectsController">
  <script>
      /* Define a JavaScript Object that looks like an Account */
      /* If you were using custom objects the name must include the "__c" */
      function Account(){
          /* Note the field names are case-sensitive! */
          this.Id = null; /* set a value here if you need to update or delete */
          this.Name = null;
          this.Active__c = null; /* the field names must match the API names */
      }

      var acc1 = new Account();
      acc1.Name = 'Tquila';
      acc1.Active__c = 'Yes';

      var acc2 = new Account();
      acc2.Name = 'Apple';
      acc2.Active__c = 'Yes';

      var accounts = new Array(acc1, acc2);

      Visualforce.remoting.Manager.invokeAction(
        '{!$RemoteAction.RemotingObjectsController.insertAccounts}',
        accounts,
        function(result, event) {
          console.log(result);
        });
  </script>
</apex:page>

The Controller

There not much to the controller in this case.

public with sharing class RemotingObjectsController {

    @RemoteAction
    public static void insertAccounts(List<Account> accounts){
        insert accounts;
    }

}

Why is this cool?

Good question. If the Force.com Platform didn’t do this for you then we – the developer – would need to convert ours types explicitly on both the server-side and the client-side, and man-oh-man is that boring, error-prone work. Yet again the guys at salesforce.com have built in a convenience that saves us time and let’s us get on with the work of building cool apps.

Written by Wes

June 22, 2012 at 11:06 am

Follow

Get every new post delivered to your Inbox.

Join 2,201 other followers

%d bloggers like this: