Moved on to Appiphony, blogging there too!

A few months back, I accepted the position of Chief Architect at Appiphony, a boutique Force.com consulting firm based in Chicago. It’s an amazing job, and I can’t imagine a better position for myself. I’ve known the founders for several years now and it’s a fantastic group to work with.

Additionally, I’ve started writing for the company blog, so posts related to cloud computing will probably appear there. My first article on testing for Force.com applications was recently posted. I’d love to hear your feedback, especially if you have either deep experience in quality assurance or Force.com. Thanks!

Custom look-and-feel with Force.com Sites and Blueprint CSS

At the core of Force.com Sites is an extremely simple, yet powerful concept: the ability to address a set of related Visualforce pages with a publicly accessible URL. Anyone with a web browser can access your application’s Visualforce pages, which in turn can incorporate a completely custom look-and-feel.

The sky is the limit…but where do you begin? Most developers investigating the Force.com platform will have a background in programming rather than visual design, and may be intimidated when building a UI from scratch.

Fortunately, there are some HTML/CSS “frameworks” that can give you a jump start. I’ve had success with one called Blueprint, and in this article I’ll show you how to use it with Visualforce and Force.com Sites.

Media_httpimgskitchco_tcqkg

A brief intro to Blueprint

In practical terms, Blueprint is a set of CSS files that provides a predefined look-and-feel for a web site, though it’s specifically designed to be easy to extend. To use it, you build your HTML as you normally would, and include the CSS classes defined by Blueprint to apply a layout and styling.

Here’s one of the examples from Blueprint’s Quick Start Tutorial:

<div class="container">
    <div class="span-24 last">
        Header
    </div>
    <div class="span-4">
        Left sidebar
    </div>
    <div class="span-16">
        Main content
    </div>
    <div class="span-4 last">
        Right sidebar
    </div>
</div>

In a typical scenario, what’s shown above would be the entire contents of the HTML body tag. Blueprint’s styling will only be applied to content within the container, providing an easy way to enable or disable it. The content will be displayed in a centered grid, which is subdivided into 24 units of width. Here’s a quick walkthrough of the remaining div tags:

  1. Create a block 24 units wide (span-24) for header content, and wrap to the next line after this block (last)
  2. Create a block 4 units wide (span-4) for left sidebar content
  3. Create a block 16 units wide (span-16) for the main content of the page
  4. Create a block 4 units wide (span-4) for right sidebar content, and wrap to the next line after this block (last)

Click on the image below to see a full sized version of the output, with Blueprint’s grid shown for clarity:

Media_httpimgskitchco_dehed

Basic grid with dummy content

This example isn’t very exciting, but with a little imagination you can see how a menu would work nicely in the header, perhaps with site navigation on the left side, and so on. Other examples and tutorials have been created as well, including one pictured below so you can see what Blueprint is capable of.

Media_httpimgskitchco_nmijj

Sample Blueprint page

Use with Visualforce

You may have realized that the CSS classes used above are defined in external files. Indeed, Blueprint’s documentation indicates that the following code should be placed in the head of the HTML document:

<link rel="stylesheet" href="path/to/screen.css" type="text/css" media="screen, projection">
<link rel="stylesheet" href="path/to/print.css" type="text/css" media="print">
<!--[if lt IE 8]>
  <link rel="stylesheet" href="path/to/ie.css" type="text/css" media="screen, projection">
<![endif]-->

In the context of Visualforce, these CSS files would become Static Resources, and the link tag would not be used. What’s trickier is handling the conditional comment for the Internet Explorer-specific stylesheet, since the head of the document is not directly accessible in Visualforce.

After some digging, I came up with this workaround:

<apex:page showHeader="false" sidebar="false" standardStylesheets="false">
<apex:stylesheet value="{!$Resource.blueprint}"/>

&lt;!--[if IE]&gt;
<link rel="stylesheet" type="text/css" media="screen, projection" href="{!URLFOR($Resource.blueprintIE)}">
&lt;![endif]--&gt;

<div class="container">
    <div class="span-24 last">
        <h1>Congratulations</h1>
    </div>
    <div class="span-24 last">
        This is your new <span class="ie-test">Page</span>
    </div>
</div>

</apex:page>

The use of &lt; and &gt; allow the conditional comment to sneak by the Visualforce parser, while still getting rendered in the browser. To validate this approach, I defined the ie-test class as being red and bold in the IE-specific stylesheet, allowing me to clearly test whether Blueprint’s IE-specific styles would only be applied in that browser.

Media_httpimgskitchco_qbajj

VF Sites page rendered in IE

Media_httpimgskitchco_frndq

VF Sites page rendered in Safari

Other features of Blueprint

Now that we’ve got Blueprint up and running, let’s dive a little deeper and look at some of its aspects that match up nicely with Visualforce. One of VF’s nicer features is the dataTable component, which provides significant power and flexibility when rendering columnar data in an HTML table. Blueprint’s default styling of tables handles this quite well.

Here’s a simple use of the dataTable component in Visualforce:

<apex:page controller="BPTestController" showHeader="false" sidebar="false" standardStylesheets="false">
<apex:stylesheet value="{!$Resource.blueprint}"/>

&lt;!--[if IE]&gt;
<link rel="stylesheet" type="text/css" media="screen, projection" href="{!URLFOR($Resource.blueprintIE)}">
&lt;![endif]--&gt;

<div class="container">
    <div class="span-24 last">
        <h1>DataTable</h1>
    </div> 

    <div class="span-14">
        <apex:dataTable value="{!accounts}" var="a" id="acctTable">
            <apex:facet name="caption">My Accounts</apex:facet>
            <apex:facet name="footer">Page 1 of 1</apex:facet>
            <apex:column >
                <apex:facet name="header">Name</apex:facet>
                <apex:outputText value="{!a.Name}"/>
            </apex:column>
            <apex:column >
                <apex:facet name="header">Street</apex:facet>
                <apex:outputText value="{!a.BillingStreet}"/>
            </apex:column>
            <apex:column >
                <apex:facet name="header">City</apex:facet>
                <apex:outputText value="{!a.BillingCity}"/>
            </apex:column>
            <apex:column >
                <apex:facet name="header">State</apex:facet>
                <apex:outputText value="{!a.BillingState}"/>
            </apex:column>
        </apex:dataTable>
    </div>
    <div class="span-10 last">
        <!-- large right margin -->
    </div>
</div>

</apex:page>

And here’s the table rendered with Blueprint’s styling:

Media_httpimgskitchco_biemr

DataTable test

Blueprint also includes some nice styles to handle user errors and notices. This maps nicely to the pageMessages component. Here’s a quick example in Visualforce:

<apex:page controller="BPTestController" showHeader="false" sidebar="false" standardStylesheets="false" action="{!throwError}">
<apex:stylesheet value="{!$Resource.blueprint}"/>

&lt;!--[if IE]&gt;
<link rel="stylesheet" type="text/css" media="screen, projection" href="{!URLFOR($Resource.blueprintIE)}">
&lt;![endif]--&gt;

<div class="container">
    <div class="span-24 last">
        <h1>PageMessages</h1>
    </div> 

    <div class="span-14 error last">
        <apex:pageMessages />
    </div
</div>

</apex:page>

Here’s the throwError method from the controller:

public PageReference throwError() {
    ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Sample error message'));

    return null;
}

And this is the rendered error widget:

Media_httpimgskitchco_glhse

PageMessages sample

Summary

Force.com Sites, when combined with Visualforce, is great in that you can present any look-and-feel to your web site’s visitors. But when presented with a blank canvas, developers may not know quite where to begin. That’s where Blueprint comes in.

Though it’s no substitute for having talented designers on your team, Blueprint usually saves time and can be very helpful for proof-of-concept work or internal applications. And what’s even better is how well it works with Visualforce and the Force.com platform.

Salesforce.com officially de-supporting IE6 in 2010…woo hoo!

I just received the below e-mail from Salesforce.com stating they’re ending support for Internet Explorer 6 at the end of calendar year 2010. It made my day…enjoy. 🙂

Dear Ross,

At salesforce.com, seamless upgrades are a top priority, and we strive to provide open communication whenever we make changes that may impact our customers. You are receiving this email because we have identified you as system administrator for a Salesforce.com organization that will be impacted by an upcoming change to our support policy for Microsoft Internet Explorer 6.0 (IE6).  We have identified that one or more users in your organization logged into salesforce.com using IE6 between September 2009 and December 2009.

What is the change?

With the Spring ’10 release, salesforce.com will begin delivering features that will not be supported for use with IE6, including our new user interface theme.  In subsequent releases throughout 2010, we may release additional features and UI enhancements that will also not be supported on IE6.  This is all in preparation for a full de-support of IE6, which is tentatively planned for end of calendar year 2010.

Why is salesforce.com doing this?

There are several reasons we are ending support for IE6:

  • IE6 is less secure. Multiple security vulnerabilities in IE6 have been exploited over the years.  The most recent attacks against Google, Yahoo, and other companies specifically targeted vulnerabilities easily accessible in IE6 but much more difficult to exploit in IE7 and IE8—leading the Microsoft Security Response Center to recommend that users of IE6 upgrade to a newer version of Internet Explorer.
  • IE6 is slow. Of all of our supported browsers, IE6 provides the slowest and least rewarding user experience for our customers.
  • IE6 is a “last generation” browser. IE6 was first released in August 2001.  As an obsolete, non-standard platform, IE6 is a difficult browser on which to develop and support the rich internet applications our customers have come to expect.

What action do I need to take?

You and your company’s IT administrators should plan and/or upgrade your users to IE7, IE8, or another supported browser by the end of calendar year 2010.

What will happen if I take no action?

Your organization can continue to use IE6 in the Spring ’10 release. However, beginning with the Spring ’10 release, salesforce.com will make available several new opt-in features that are not supported on IE6.  Your organization has the option of leaving these features inactive until you have upgraded to a supported browser.

How can I get more information?

Please contact salesforce.com Customer Support with any questions you may have.

Best regards,

Salesforce Customer Support

support@salesforce.com

Remote Sites + load balancing = a Force.com gotcha?

My favorite aspect of developing on the Force.com platform is how quickly you can get something up and running. Recently, I’ve been chewing on an idea for how to better the integrate the photos I share on Twitter into my personal blog on Tumblr, though it would require a little bit of coding. I had a little downtime today and got almost all the way there.

Background

As I mentioned, I keep my personal blog on Tumblr. It’s a neat tool, and I’ve always liked the way that it can pull in content from other sources (usually via RSS) and aggregate everything you’re sharing online. I’m active on Twitter, so naturally I configured my tumblog to read in the RSS feed of my tweets. This works great for short text blurbs, which is the heart and soul of Twitter.

A picture is worth a thousand words, of course, and being an amateur photographer I often post quick snapshots on Twitter via yFrog, one of several services that extends Twitter to provide photo sharing. These tweets will include a shortened URL to the photo, which makes perfect sense in your Twitter feed but leaves room for improvement when that same tweet is copied onto a blog. Tumblr includes a native post type for photos, so my idea is to have a piece of code sweep through my Tumblr posts looking for links to “yfrog.com” and replace those posts with full-fledged photo posts.

As luck would have it, both Tumblr and yFrog offer REST APIs that allow this type of thing to be straightforward. The flow of the code is basically as follows:

  1. Read in recent Tumblr text posts (via the Tumblr API), and keep a list of those that include links to yFrog
  2. Run through that list and use the yFrog API to determine the URL to the full size image for each
  3. Create a Tumblr photo post for each that links to the URL from step 2 (rather than uploading an actual image)
  4. Delete the original Tumblr text posts that would then be a duplicate

Unfortunately, I ran into a problem at step 2.

The Issue

Force.com requires any sites that your code will access via HTTP to be specifically whitelisted under Setup → Security Controls → Remote Site Settings. In the case of Tumblr, blog entries are created by sending an HTTP POST with various parameters to the following URL:

http://www.tumblr.com/api/write

The screenshot below shows the Remote Site configuration used for that example:

Remote Site configuration
Remote Site configuration for Tumblr

Accessing the image metadata via the yFrog API is conceptually similar, except the HTTP GET request is redirected to a different URL (presumably for load balancing purposes). Here’s a screenshot from HTTP Client that shows the actual response:

Image API call redirected
HTTP response being redirected

The Location header provides the URL that now accesses this resource. I changed my Apex code to account for a possible redirect, but then I ran into a problem with the Remote Site:

Remote Site error with dynamic subdomain
Remote Site error with dynamic subdomain

The part of the URL underlined in red is the part that would generally need to be configured as the Remote Site URL. However, this isn’t practical, since each time the initial GET is performed, the redirected URL has a different subdomain. Again, this is understandable as a load balancing mechanism, but unfortunately puts the brakes on my mashup.

Possible solutions

I can appreciate that the Remote Site provides a layer of security, though perhaps a compromise would be to allow wildcards in this configuration, as in:

http://*.imageshack.us

Alternatively, the platform’s native HTTP mechanism could automatically follow those redirects, similar to how this is handled in Google App Engine. That would eliminate the need for the Apex code to handle redirects.

As a workaround, I’ve started sharing images with a service called Twitgoo (instead of yFrog). They have an API as well, and calling the methods does not result in a redirect.

GET http://twitgoo.com/api/message/info/3spr5

Here’s an example response:

<?xml version="1.0" encoding="UTF-8"?> 
<rsp status="ok"> 
   <created_at>2009-11-09T09:29:41-07:00</created_at> 
   <username>twitgoo_test</username> 
   <avatar>http://a3.twimg.com/profile_images/107548761/bad_rooster_normal.jpg</avatar>
   <statusid>4417243089</statusid> 
   <mediaid>3spr5</mediaid> 
   <mediaurl>http://twitgoo.com/3spr5</mediaurl> 
   <text>Awesome Denver city lights</text> 
   <imageurl>http://i35.tinypic.com/17tzde.jpg</imageurl> 
   <thumburl>http://i35.tinypic.com/17tzde_th.jpg</thumburl> 
   <viewcount>31</viewcount></rsp> 
</rsp>

Crisis averted. 🙂

Force.com Sites and the hidden Profile

Salesforce.com has been a leader in the SaaS and PaaS markets since those buzzwords were coined, though as a web developer my interest was piqued with the advent of Force.com Sites. For the uninitiated, Sites is a feature of the Force.com cloud computing platform that allows a developer to create a publicly available web site or application with a completely custom UI. The native look-and-feel of Salesforce.com is great for a broad category of business applications, but Sites allows you to shoot for the moon with your user experience.

Sites builds on Force.com’s native capabilities, allowing developers to use powerful technologies like workflow and fine-grain security controls without building them from scratch. Since most organizations will need to enforce some level of data security, it’s worth exploring how that intersects with making information available to the public.

The hidden Profile

If you’ve worked with Salesforce.com for any length of time, you’ll no doubt be familiar with the concept of a Profile. Essentially, a Profile is a set of privileges which can be granted to multiple users to avoid the grunt work of configuring security on a user-by-user basis. A detailed discussion of Profiles is beyond the scope of this blog post, though they are documented extensively elsewhere.

Force.com Sites also leverages the concept of a Profile to determine which pieces of data are visible on a given web site, though it’s not immediately obvious that this Profile is hidden. To be more specific, a new Profile is created automatically by the platform when a new Site is created. The name of this Profile is the site’s Label, followed by the word “Profile” (as shown below):

Media_httpimgskitchco_drygk

Site configuration

When viewing the list of Sites configured for your org, click the Site Label to view the screen above. From there, click Public Access Settings to view the details of the hidden Profile.

Media_httpimgskitchco_qjfku

The Profile generated automatically for that site

The name of the Profile is worth noting, especially when it comes time to deploy the site to a production org. Configuring a Profile can be a bit tedious and error prone, so once this is done correctly in a sandbox, it’s convenient to migrate this configuration rather than rebuilding it. When migrating with Eclipse, this hidden Profile will appear in the list of objects that can be deployed to another org, but it is not shown on the list of Profiles viewable under Setup in the web UI.

Media_httpimgskitchco_ftfcw

The new profile is missing from this list

This simple fact can make the security configuration of a Site somewhat confusing, but once you become familiar with it, the mystery goes away. The fact that this Profile is hidden is beneficial for large organizations that have many individuals administering a single Salesforce.com org, not all of whom may understand the purpose of every Profile.

Summary

It’s not uncommon to get tripped up by security configuration issues when beginning to work with Force.com Sites. The key is to simply configure the hidden Profile correctly in a sandbox, then migrate that profile to production rather than rebuilding it by hand.