Skip to content
Jun 28 11

Display Inaccessible Objects to (Salesforce) Portal Users

by Clint Lee

Off Limits

It’s quite late, and I can’t think of anything particularly clever to say, so I’ll just get straight to the point.

If you’ve ever built a custom portal using Salesforce Sites then you’ve most likely had to navigate your way through the various portal licenses at some point. Let’s see, there’s a Customer Portal, a High Volume Customer Portal, an Authenticated Sites, and perhaps another one. Oh yeah, then there’s the Public Site profile.  Each license has its own nuances – object access, CRUD permissions, cost.  Inevitably you’ll need to decide on the license type that best fits what you’re trying to do, knowing that you might have to concede something down the road as you hit a gotcha! or two.

I came across a particular situation where I needed to display information from the Account object to the user.  The Site being built utilized the Authenticated Sites portal license (which provides user authentication but requires a lot of development since it requires only Visualforce pages).  Unfortunately, the Authenticated Sites license doesn’t provide the user with access to the Account object.  When I say no access I mean they can’t even read it.  So, a workaround ensued…

The following solution is not particularly mind-blowing, or really even that sophisticated, but it works for displaying data in what could be termed as “inaccessible” objects.  These are objects that Authenticated Sites licensees can’t read like Accounts, Opportunities, and Cases.  Enter….(drumroll, please)…the Wrapper Class.  Yes, folks, the Wrapper Class.  To most, this was probably obvious from the start but for me it took some noodling around.  Therefore, I decided to share in an effort to prevent others like me from noodling for too long.

Go ahead and create a wrapper class for your object, like so. Name it whatever you like. I call mine AccountToString b/c it sounds fancy.

public class AccountToString {
	   private Account acct;

	   public AccountToString(Account acct) {
	   	      this.acct = acct;
	   }

	   public String getName() {
	   	      return acct.Name;
	   }

	   public String getAddress() {
	   	      return acct.BillingAddress;
	   }

	   public String getCity() {
	   	      return acct.BillingCity;
	   }

	   public String getState() {
	   	      return acct.BillingState;
	   }

	   public String getZip() {
	   	      return acct.BillingPostalCode;
	   }

}

Write a controller method to turn your accounts into AccountToStrings. I needed a table with Account data so I populated a class variable with a list of AccountToStrings. Here’s an example.

// This method could run in the controller's constructor.
public void findAccounts() {
           List<Account> accts = [select Id, Name, BillingAddress, BillingCity, BillingState, BillingPostalCode from Account];
           for(Account a : accts) {
                 AccountToString aString = new AccountToString( Name = a.Name, BillingAddress = a.BillingAddress, BillingCity = a.BillingCity, BillingState = a.BillingState, BillingPostalCode = a.BillingPostalCode);
                 aStringList.add(aString); // aStringList is a public class variable
           }

Finally, in your Visualforce page, this is one way that you could access your list of AccountToStrings.

<apex:page controller="MyPortalController">
    <apex:outputPanel layout="block">
        <apex:dataTable id="mytable" value="{!aStringList}" var="a">
             <apex:column >
                  <apex:facet name="header">Account Name</apex:facet>
                  <apex:outputText value="{!a.name}" />
             </apex:column>
             <apex:column >
                  <apex:facet name="header">Address</apex:facet>
                  <apex:outputText value="{!a.address}" />
             </apex:column>
             <apex:column >
                  <apex:facet name="header">City</apex:facet>
                  <apex:outputText value="{!a.city}" />
             </apex:column>
             <apex:column >
                  <apex:facet name="header">State</apex:facet>
                  <apex:outputText value="{!a.state}" />
             </apex:column>
             <apex:column>
                  <apex:facet name="header">Zip</apex:facet>
                  <apex:outputText value="{!a.zip}" />
             </apex:column>
          </apex:dataTable>
     </apex:outputPanel>
</apex:page>

I hope this makes sense and perhaps saves you some time. As always, I look forward to any comments or feedback.

Jun 23 11

Summer ’11 Master-Detail Quirk [UPDATED]

by Clint Lee

Salesforce Summer 11 Logo

*****UPDATE June 30, 2011******

Shortly after this post I was contacted by Salesforce’s Apex product manager who wanted to follow up on this issue and help resolve it.  Major kudos to Salesforce for monitoring the blogosphere and addressing the problems of their partners and customers.  After spending some time trying to recreate this problem the SFDC team could not replicate it, and so apparently whatever was causing this quirky issue to happen has been resolved, effectively making the rest of this post obsolete.  But, you can read on for the history if you’d like… ;)

*****************************

The good news about working on the Salesforce platform is that three times a year, while you’re lying asleep at night, the little Salesforce elves are hard at work rolling out the newest release.  The bad news is that sometimes on a Monday morning you start seeing Apex errors in your inbox.  This past release of the Summer ’11 upgrade was one of those times for me.  I thought I’d share the details to prevent anyone else from banging their noggin’ against the wall.  Spoiler Alert! The story ends happily with a working solution.

The Background

We had a portion of Apex code that, when executed, created a custom object which was the detail side of a master-detail relationship.  Nothing special going on here, just straightforwardness.

The Problem

On the Monday morning after the org was upgraded to Summer ’11 errors started to kick off whenever this particular piece of code was executed.  The error given was “Field Not Writable” and it referred to the lookup field that looked up to the Master object.  For all the visual learners out there (like me!) see the diagram below.

Master-Detail Visual

Whenever an Object B was attempting to be inserted we would get an error on Field 1 saying “Field Not Writable”.  Very strange since two days earlier this was working splendidly and nothing had changed since.  After quite some time of trying to track down the root problem we submitted a Case to Salesforce assuming this was some bug related to the upgrade.  As it usually goes, shortly after submitting the case we developed a solution that worked.  Here it is…

The Solution

This is actually so simple it hurts.  The object was being created like this.

Object_B__c objB = new Object_B__c();
objB.field1__c = objectAId;
insert objB;

The solution was simply to instantiate the Master object field in the constructor. Like so…

Object_B__c objB = new Object_B__c(field1__c = objectAId);
insert objB;

A very subtle quirk in the new release but nonetheless one that can cost you hours of time trying to understand and resolve.  Salesforce support did respond and let me know that they were unaware this change had happened.  The case was forwarded on for analysis.  No word yet on whether this was intended or unintended but for now all is good.

I hope this helps and as always I look forward to any comments or feedback.

May 28 11

Will Database.com Handle Big Data?

by Clint Lee


I’m really looking forward to next week’s sneak peek webinar of Salesforce’s new DaaS (database-as-a-service) appropriately named Database.com. Salesforce is touting the new service as the premiere cloud database for enterprises “that is designed for the next generation of collaborative, mobile and real-time apps.” The question I have is will Database.com give any real or affordable options for handling big data?

What is Big Data?
To simplify, big data refers to datasets that are so large they become unmanageable using traditional database management tools (think hundreds of terabytes or event petabytes of data). Big Data datasets can also be highly unstructured, meaning that the data in them doesn’t fit neatly into a traditional relational database. Handling this type of data requires new sets of tools and frameworks that are designed for capturing, storing, searching, and analyzing such large amounts of data.

But Who Needs to Worry About Processing This Much Data?
In the past, the problems associated with handling datasets of this size might have been limited to only the largest research institutions like NASA, CDC, National Weather Service, etc. However, with the explosion of new social and mobile applications and the ubiquity of mobile devices it’s no longer unthinkable to amass such large datasets. For example, there are more than 30 billion (yes, billion) pieces of content shared on Facebook each month. All of these data points have to get stored in a database, right? Yep. And when you login to your Facebook account the system has to query all of your friends, then query all of your friends’ shared content, and then display it in your news feed – all in a matter of milliseconds. Now multiply that by 600 million users.

Database.com is for the Enterprise, Not Wannabe Facebook Startups, Right?
Right. Well… wait. Actually…well, I’m not sure. This is a good question. Although I follow Salesforce pretty closely and stay on top of what’s happening in the community I’m still uncertain as to Database.com’s ultimate business model and who it’s mainly geared toward. With Database.com’s pre-built toolkits for Ruby, iOS, Android, PHP, and it’s recent acquisition of Heroku it would seem as though Salesforce is targeting web application developers in general who need a scalable database. I could also see existing Salesforce CRM or Platform customers building Business-to-Consumer web applications that are integrated with their existing Salesforce database. But as your active user base increases, and if you provide social and mobile aspects to your application, then your content storage, search, analysis, and computational needs are going to increase as well. And if there’s one thing I know about Salesforce it’s that additional storage capacity gets quite expensive.

What’s Out There for Managing Big Data?
This is an enormous topic and well beyond exploration in the scope of this post. However, there are a number of technologies that have emerged in the last several years, primarily from Google and Yahoo, since internet search engines were among the first companies to encounter the challenges with big data.

Open Source technologies such as Hadoop, MapReduce, and BigTable are among the core of big data management. It essentially requires spreading out the storage and transactional computations among a distributed network of servers. Companies like CloudEra have emerged to offer services and proprietary software that help companies more easily implement and maintain these data management systems.

Here are some additional resources on Big Data:
Read More…

May 18 11

Klout + Salesforce = Identify Your Social Influencers

by Clint Lee

Klout Logo

As these things often do, this project came about as I was searching for the solution to a problem. I couldn’t find anything that worked so I decided to try and solve it myself.


The Use Case

I was working with one of our clients on a Salesforce implementation and since they’re very active on Twitter they naturally wanted to take advantage of the Salesforce For Twitter app by ForceDotCom Labs. We decided to incorporate a Twitter Username field into most of their web forms and after a short time they had begun to capture a large number of twitter usernames for their Leads and Contacts. We’d also been discussing the idea of the emerging new science around measuring an individual’s social influence. Tracking and understanding someone’s social influence has broad applications for businesses and non-profits alike. For marketers wanting to spread information about a new product, to non-profit fundraisers wanting to disseminate information about an upcoming event, knowing who your most socially influential contacts are might be a handy piece of information to have. But how do you track this information?

The Solution
It seemed obvious to start with utilizing Klout for their influence scoring. Klout seems to be the gold standard when it comes to social influence measuring tools. I first looked on the AppExchange to see if there was an existing tool that connected Salesforce with Klout. No such luck. Next, I googled and searched my way around the Salesforce community looking for something that would accomplish the task at hand. Hmmm…no luck again.

Long story short, I ended up with a tool that lets you pull Klout directly into Salesforce based on a Lead or Contact’s Twitter username. This is available in an unmanaged package and I also submitted it to the Salesforce Code Share in case anyone wants to improve upon it. You can view the video below for an overview and install the package here.

Demo

For anyone interested in the source code, you can find it here on GitHub.

As always, I look forward to any feedback and comments.

Mar 1 11

Got Data? A Salesforce and Rapleaf Mashup

by Clint Lee

Salesforce-Rapleaf Mashup – A 4:00 Overview

Any company with customers and/or prospective customers ought to know about customer segmentation.  I mean all customers (and prospective customers) are not equal, right?  Some are older, some are younger.  Some live here, some live over there.  They have different interests, backgrounds, and even purchasing histories.  Customer segmentation gives you the ability to tailor targeted messaging to specific channels of your business, or even to develop algorithms to predict customer retention, among numerous other benefits.  Anyone with a database of customers and prospects should be employing some level of customer segmentation.

This thinking should naturally lead to the questions:

  • What information about my customers and/or prospects do I need?
  • Where do I find this data?
  • What if I only have a limited amount of information to start with?
  • How long will it take to gather this info?

After thinking through these questions myself, and doing some research, I found a company named Rapleaf.  Rapleaf’s proclaimed mission is to “create a more personalized world”.  They do this by aggregating a potentially large amount of data and building a profile around email addresses.  This is unique because the only piece of information that you really need in order to access their database is an email address.  Since an email address is something that we typically have for most of our customers and prospects this service looks like it could be pretty valuable.   This led me to a few more questions such as, “What type of information can I get?”, “How much will it cost”?, “How accurate is Rapleaf’s data”?, and “How can I integrate it with Salesforce”?

I checked out the API docs to understand how to access Rapleaf’s database, and after trading a few emails  with Rapleaf’s Co-Founder Manish Shah I was able to get a full listing of potential data and pricing.  Setting up a free account with Rapleaf will get you an API Key and access to unlimited age, gender, and location data queries.  There are many additional fields available, and since it’s my understanding that Rapleaf is working on revising their pricing, you can just contact them and they’ll be happy to go over the cost structure with you. 

I searched the Salesforce community and didn’t find any existing code for integrating with Rapleaf so I decided to build something myself in Apex and share it.  There are three classes that handle the Rapleaf mashup, Rapleaf, RapleafResponse, and RapleafSetup.  I’ve also included a sample trigger for fetching Rapleaf data when a new lead is inserted.  Test classes are included, as well.  The full source code can be downloaded here. It basically works like this:

Read More…