integration
March 10, 2008
David Glick: collective.recipe.omelette: for more navigable eggs
Crack 'em open and mix 'em together...
I've been using zc.buildout for a few months now, and am quite happy with it. However, I got tired of navigating to my egg cache, locating the right package (and version) within a long flat list, and then clicking a few more times to actually get to the contents of the package. And I was looking for a project to practice my buildout recipe fu.
So I created collective.recipe.omelette. It's a simple buildout recipe that takes all your namespace-packaged eggs and merges their contents together into a single directory tree, in its own parts directory, with symlinks to the actual egg contents. The result looks much the lib/python of days gone by. So instead of:
egg-cache/ my.egg.one-1.0-py2.4.egg/ my/ egg/ one/ (contents of first egg) my.egg.two-1.0-py2.4.egg/ my/ egg/ two/ (contents of second egg)
you can now make use of:
parts/ omelette/ my/ egg/ one/ (contents of first egg) two/ (contents of second egg)
with obvious advantages in navigability and greppability.
Collective.recipe.omelette is available from the Cheese Shop. You can add an omelette to your buildout by making the following additions to buildout.cfg (assuming you have a part called instance and you want to generate symlinks for its eggs), and then re-running your buildout:
[buildout]
...
parts =
...
omelette
[omelette]
recipe = collective.recipe.omelette
eggs = ${instance:eggs}
One caveat: Since this makes use of symlinks, it of course won't work on a filesystem that doesn't support symlinks, such as Windows'.
February 16, 2008
Andrew Burkhalter: Increasing Documentation for and Visibility into Plone's Efforts to Integrate with Others
Seeking comments on a plan to "make sure the "strategic integration" story with other systems is visible and documented" as follow-up from the recent Plone Strategic Planning Summit.
On the off chance that you're like me and prone to falling behind on your various Plone list-related reading, I'm soliciting feedback on my plan for ticket #7813 aiming to "make sure the "strategic integration" story with other systems is visible and documented". Comments welcome. Full plan below:
With ongoing support, feedback, and guidance from the broader Plone
community, I volunteer to serve as "champion" of trac issue #7813,
'Make sure the "strategic integration" story with other systems is
visible and documented' (http://dev.plone.org/plone/ticket/7813). I
will do so by offering to invest time/energy within the following two
focus areas:
1) Developing code, making increasingly better releases, documenting,
and marketing for the Plone integration with Salesforce.com as the/a
Plone Customer Relationship Management (CRM) story
2) Beg, bribe, borrow, and steal case studies and documentation of
successful implementations of Plone integrating with system X for
plone.net and plone.org/documentation. I'm not able to offer code in
this department, but I will aim to highlight successes and possibly
over time aggregate pain and resources for new integration territories
we'd collectively like to explore.
=-=-=-=-=-=-
Deliverables - I.E. what will exist in 6-9 months
=-=-=-=-=-=-
Plone with Salesforce.com serving as CRM:
- Increasingly more mature releases of the following suite of
products: http://snipurl.com/plonesfproducts
- A solid manual at:
http://plone.org/documentation/manual/integrating-plone-with-salesforce.com
- Personal and Plone community participation in:
http://groups.google.com/group/plonesf/topics
- Increased use of the term "CRM" in close proximity to the word
Plone, so that folks Googling for a CRM that works with Plone see this
as a strength for Plone, rather than a weakness.
Shed light on the "strategic integration" story:
- 3-5 "integration-centric" case studies exist on plone.net
- A "3rd party integration" category for: http://plone.org/products.
Ensure tagging is happening.
- Enhance "Plays well with others" section of Plone.org homepage
under the "Standards Compliant" section
- Bonus points: Hightlight commonly needed integration stories
hopefully causing new tools/documentation to emerge
=-=-=-=-=-=-
What success looks like
=-=-=-=-=-=-
I don't think the above alone will accomplish this, but it's a start.
I think longterm success would be:
- Members of other software communities (i.e. Salesforce.com, Moodle,
Facebook, <insert system that can be integrated with here>) learn
about and deem Plone a viable and *complimentary* CMS. This knowledge
is learned within the context of their existing communities.
- Integrates well with X is easily found and helps certain decision
makers decide to use Plone. Seminal "why we chose Plone" blog posts
appear citing integration as a key reason :)
- Plone continues to thrive by staying focused on what it does best
(as seen with future code Plone releases). When strategic, Plone
integrates nicely in order to avoid spreading itself too thin.
=-=-=-=-=-=-
Call for Participation
=-=-=-=-=-=-
If Plone's integration makes you excited. Logical next steps include:
1) Give me feedback on this plan
2) Watch ticket #7813 at http://dev.plone.org/plone/ticket/7813
3) Tell me on list of off list what you've integrated Plone with and
why you think it's interesting. We'll turn interesting stories into
case studies.
4) If Salesforce.com as a CRM for Plone excites you, join this Google
Group: http://groups.google.com/group/plonesf/
Hopefully this is pretty clear and actionable. I look forward to the
ensuing discussions. Let me know what I'm missing and what seems
vague or unachievable.
February 14, 2008
Andrew Burkhalter: In the Wild: PloneFormGen Speaking Directly to Salesforce.com ...
The Salesforce Adapter for PloneFormGen sees the light of day.
... or "So, we're hiring a database developer to help with CRM implementations ..." But, that alternate title isn't really the point (unless you're interested ;) )
As far as I know, the following PloneFormGen "Form Folder" is the first publicly available, advertised, and production use of the Salesforce Adapter for PloneFormGen (please correct me, if I'm wrong). If you haven't heard about this piece of code that connects Plone to Salesforce.com via PloneFormGen, you might want to start here or here.
This is great for a couple reasons:
- The particular use case (i.e. collecting applicants for an open job offering) is one that I certainly never would have thought of -- and that's the point. Creating these shouldn't take a Plone developer. Nor should coming up with the possible use cases. It should be the responsibility of staff that need to build the relationships they need in order to do their work. My colleague Steve is no slouch with CRM and Salesforce.com, but the portion of getting this on our Plone-powered site doesn't take any additional expertise.
- It will help flush out any bugs, so that we can push onto a more mature-sounding release (i.e. final, not beta or release candidate)
- It comes equipped with the following explanation, which I think is fantastic:
Geek FYI: this is a form built in Plone that sends your data directly to our Salesforce.com database. We'll receive a notification when that data gets created. You'll also be automatically added to a Campaign that will capture all applicants. I've got a view in the Console for keeping track of all the applicants for this position. If you understood all that, or really want to, that's a good sign...
So, um, test it out if you want...
January 24, 2008
Alan Runyan: Enfold Desktop 4 - Free and Server Independent
Enfold Desktop is now server agnostic and free. Desktop will work with any DAV server including: Zope, mod_dav, IIS, etc. Plone is no longer a requirement. Also its has a much better user experience than any previous version. A must-have for Windows users.
Finally the software has been released. Last year there was a Ploneability High Education event held in November at the University of Houston. I promised a few things during that presentation. We have followed through and I want to explain to the wider community our motivations.
At the Ploneability event I said Desktop 4 would be free. Desktop is now available to download. I also want to highlight some features: decoupled Desktop from Plone, the UI is now mostly asynchronous, fixed tons of bugs. We now feel that Desktop 4 should be widely distributed and urge everyone to use it.
Specific highlights:
- Enfold Desktop no longer requires Plone. The Desktop Server components for CMF/Plone add "more functionality" to the user's experience. Such as workflow control and property sheets. But the server components are no longer required. In this mode Desktop users simply have fewer options. They have a very nice and reliable DAV client that is more predictable than Microsoft
Web Folders. You can now use Enfold Desktop with Plone, Zope, CMF, mod_dav, IIS, etc. In fact we urge you to use it on any DAV server! - Performance. The UI was originally synchronous. This meant you could do one thing at a time. If an operation took a long time (say uploading a 100MB file) your Enfold Desktop would become unresponsive. This is no longer the case. You can upload and download multiple files at once and edit files -- all simultaneously! The user experience is significantly better because of these performance enhancements. Give it a shot and tell us.
- Bug squishing. Not much else I can say. We added a
Report a bugfeature. Also if desktop does something unexpected it will prompt the user to send us a message (it also sends internal logging). This has helped tremendously. We have uncovered loads of bugs and fixed them. Often bugs that end users were unaware of but were still happening under the covers.
Why we released:
Enfold Systems is very interested in acting as a good community citizen. We believe that Enfold Desktop will enable people to win more consulting projects. If they want support and to remove the ads - they can pay us. But the result is the consulting community is often asked for Windows Desktop integration and there was no de-facto standard. Enfold Desktop aims to be that standard. By having the broadest adoption of Enfold Desktop there will be a coherent Plone / Windows Desktop integration story.
This is only the beginning. We have laid one piece of the foundation. Plone has a complete DAV integration (server and client). But it needs much more. Specifically we need software developers to make their software DAV compliant. This requires the entire community to buy-in. There are many reasons for DAV compliance. One example could be import/export.
An example is having a representation of content outside of the CMS, say in the case of exporting. Also a way to create content by importing this representation. So the import/export story, I believe, could be tied to having a DAV representation for content. Plone still does not have a full import/export story that is 100% textual and independent of the storage medium. Customers want repeatable import/export.
Another could be creating a cross platform editor for content. We now have Enfold Desktop and External Editor. But we can not edit "rich content types". This could be very interesting. Double click on content and have it open up in a rich editor that supported calendar controls. We have a higher level of abstraction other than "File". It would be a pity for everything to be file oriented.
If you do not keep up with IT analysts writings. Plone is the big kid on the block when it comes to Open Source content management. Desktop integration is one facet to CMS. The plone community now has a great foundation to make a much richer experience. And an immediately useful Folder/File-level DAV integration for the Windows Desktop. But it will require more from the community. Specifically users asking product writers to support DAV. Because it is the product aftermarket that makes the Plone CMS so powerful. Commercial CMS's do not have such a flourishing aftermarket. The Plone aftermarket is continually building and sharing 24 hours 7 days per week.
Lastly I would like to clarify Enfold System's position when it comes to open source and Plone. Enfold Systems is the Windows open source content management system specialist. We focus on providing product, services, and integration to organizations that want the power of the open source Plone content management system while reusing their existing Windows infrastructure. This is very important for large organizations. This is our niche. Our customer's want a vibrant community. So as we provide service to a wide variety of organizations from small-medium size non-profits to fortune 100 companies - Enfold Systems is trying to build a sustainable open source model. A part of this manifests in big releases like Enfold Desktop 4 being released. But more often than not you can see aftermarket Plone components such as the magnificent UploadReferenceWidget and the visionary Entransit Content Deployment all the way to unseen bug fixes to Python COM bindings, Zope, and Plone. PLIP 187 is an example of us feeding changes from product development back into Plone proper. Enfold Systems sees releasing Desktop as a way to grow the Plone ecosystem. Also to maintain visibility that Enfold Systems is both the premier Open Source Windows CMS provider and the Plone experts.
August 21, 2007
Andrew Burkhalter: Salesforce Base Connector for Plone 3.0
Alpha 2 release of the base connector for Plone 3.0.
With a huge thanks to the authors of Updating add-on products for Plone 3.0, Limi, Martin, Geir, Sisi, and others, it was a breeze to get Salesforce Base Connector working for Plone 3.0. We just pushed out another release, so that it doesn't appear DOA after putting out a non-3.0-compliant release last Friday. It's still very experimental, but now testable with the latest and greatest.
August 11, 2007
Andrew Burkhalter: New Salesforce PFG Adapter Release Up on the Plone Software Center
Salesforce PFG Adapter 1.0 alpha 2 up on the Plone Software Center with several key usability enhancements to the field mapping user interface.
While creating a working demo for my post on Saving PloneFormGen Data Directly to Salesforce.com, I was reminded of and discovered several new irritating bugs present with the current field mapping user interface.
Jesse Snyder and I were able to pick of several of these during today's ... er, yesterdays ... Open Source Friday session and package up a 1.0 alpha 2 release. Fixes include:
- Due to some trailing and proceeding character stripping that happens within DataGridField's FixedRow implementation, inadvertently named fields like "My Form Field with Trailing Spaces " (spaces intentional), could never be successfully mapped to a Salesforce.com SObject field. NB: We're still using the Title of form fields as the "key" for our mapping, which has its limitations, but is easiest in this more proof of concept phase of work.
- Because we're eliminating a user's ability to wipe away form fields by disabling DataGridField's add/remove row features (this is by design, as a "read-only" paradigm is much clearer for users), re-titled and deleted fields were polluting our available form fields for mapping user interface. We've now got code that cleans up those form fields which are unmappable to Salesforce.com SObject fields anyway.
- We've also got a nice little, fully passing suite of 25 tests, which is starting to get into the realm of respectable for our code base.
Up next is likely to be i18n work, improving usability around a chosen
SObject's required fields, and enabling the mapping of PloneFormGen's
DateTimeField to Salesforce.com's Date/Time string format.
Let us know if you come up with anything that's not currently on our todo list.
August 09, 2007
Andrew Burkhalter: Saving PloneFormGen Data Directly to Salesforce.com
For this next installment in my series of posts on integrating Plone & Salesforce.com, we cover the tools useful for an integrator aiming to allow those in the content editor and site administer space (albeit the more technical ones) to integrate with Salesforce.com without ongoing developer intervention. The first post mostly covered the underlying technical infrastructure, while the second was of the integrator variety and described how to display Salesforce.com data within Plone using Zope's templating machinery.
The Background
The more I've dug into and studied PloneFormGen, the more enthusiastic I am about it as a project, concept, and code base. I think readers of this post already likely have a lot of respect for how SteveM conducts the project, but I'm also continuously impressed with the amount of flexibility that's built into the code base. In this case, I'm talking about the ability to add custom action adapters. In the NGO-space, it really doesn't get much more critical than allowing content editors to build forms that collect information from would be constituents.
Someone in the Open Source Friday crew (I believe it was Brian Gershon or Jon Baldivieso), thought up the idea of writing our own custom action adapter for PloneFormGen that stores form data directly to Salesforce.com. Seeing as we use Salesforce.com as a constituent relationship manager and PloneFormGen to do things like sign constituents up for email alerts, volunteer opportunities, and events, cutting out the extra data entry is ideal.
In PloneFormGen's SaveDataAdapter and FormMailerAdapter we have a perfect example of an incredibly useful action adapter and what it would take to create our own for PloneFormGen. In addition, we already have Salesforce Base Connector providing a bridge, via beatbox, to Salesforce.com via its SOAP API. With these pieces in place, creating our Salesforce PFG Adapter was significantly easier.
Setting it all up
First, make sure you're all caught up with the setup from the previous post (you can stop when you get to the section titled "The Code"). Once you've stepped through that, it's just a matter of getting the dependencies needed for Salesforce PFG Adapter. These include:
- PloneFormGen
- Scriptable Fields (bundle)
- Salesforce PFG Adapter
- DataGridField - At the time of this writing, you need a particular
branch from the Archetypes subversion repository. The following within
your Products folder should do:
svn co https://svn.plone.org/svn/archetypes/MoreFieldsAndWidgets/DataGridField/branches/1.5-RC1 ./DataGridField. Hopefully, that won't be the case in the future.
svn co https://svn.plone.org/svn/collective/PloneFormGen/adapters/salesforcepfgadapter/bundles/ ./ Once you have all these items, restart your instance and use the quick installer to add Salesforce PFG Adapter as shown below (this will ensure that all dependencies are also added):

Salesforce PFG Adapter in Action
This is all hypothetical, but let's say you run a website that encourages users to submit information about upcoming concerts featuring local artists in an effort to market regional arts. Your goal might be to display this in a calendar on your site. This alone, would not be reason enough to integrate with Salesforce.com, as we've already got the event content type available in Plone.
However, to add a twist, let's say you also want to award prizes to those that submit the most events, send users annual appeals to donate to your organization, and use the events most frequently submitted to determine where you should be doing advertising for your organization. The logic of these tasks already live in your CRM. Something along these lines would be a pretty common nonprofit story and would require one to do a lot of custom programming with Plone. A better option would be to integrate your Plone site with an existing Salesforce.com application.
If you've got PloneFormGen, you might setup the following form (it's a bit unrealistic, but you get the idea) for your site:

By default, you can get this emailed to you. But, that introduces the boring, error-prone manual data entry problem when you want to get this into your CRM. With Salesforce PFG Adapter and a standard Salesforce.com instance, we can take care of this data directly.
I deliberately created a more complicated example to highlight the capabilities of PloneFormGen and our Salesforce PFG Adapter, but let's start with the basics.
First and foremost, we have 3 fields (first name, last name, and email address) that are not intended to be a part of the event object itself. Remember my use case above where I describe needing to send out annual appeals to all those submitting events, thus encouraging them to donate to your organization. We use these fields to build up our pool of engaged Salesforce.com contacts.
Using the add new item menu on our Form Folder, we add our first Salesforce PFG Adapter.

The title is unimportant. The "Salesforce Object Type" field however presents a list of eligible SObject types your Salesforce.com instance has to offer. I choose contact in my example.

From there, we hit next until we get to the "Field Mapping" section of our Salesforce PFG Adapter. This is where things get interesting. Using the DataGridField, we present a mapping-like UI for choosing which Form Fields should be associated with their corresponding SObject fields. The drop down list of SObject fields are limited to only those associated a Contact, the chosen SObject type on the first screen of the created Salesforce PFG Adapter.
The following screen shot shows how I mapped my contact-related form fields:

Next, we disable the default enabled Form Mailer Adapter and ensure that our Contact Adapter is selected.

A quick test of the form, with the following data...

... yields a new contact in Salesforce.com:

At this point, nothing is happening with the remainder of the form data. This is by design. You may choose to retrieve the rest of the form data with a different adapter. Lo and behold, this is what we want to do :)
After adding another Salesforce PFG Adapter to our Form Folder and providing a title, we choose the Salesforce.com "Event" SObject type:

We then provide a mapping of those form fields we want associated with the newly created Event object:

Going back to our form we now fill out the entire form with data from a fictitious user for an upcoming show I'm looking forward to attending :) ...

In the interest of full disclosure, the Event SObject is actually one of the more complicated data types we could choose to create. We're getting around this a bit by assuming the user will submit an appropriately formatted date/time string and an integer with the duration in minutes of the event. The real world doesn't work like this (see "What's Next?" below), but these are Salesforce.com Event object requirements. Additionally, to fulfill my use case where awards are given to those submitting the most events, I add a custom field "Submitted by Email" to my event type. The *right* way to do this would be to use a lookup to get the unique id of the newly created contact. This will require some additional features to be added to Salesforce PFG Adapter (again, see "What's Next?" below).
Heading over to our Salesforce.com instance, we now have the newly created contact:

As well as the event, which is associated with the email address of the submitting user:

All this, with no manual data entry required. Bring on the user contributed content...
Why?
Hopefully, the motivations for this work are pretty clear. However, just for emphasis, I want to point out some of the reasons why I think this is pretty neat:
- It's true -- Salesforce.com already provides a utility called Web2Lead that allows for easy form creation. This, however, creates a Lead SObject, which can only be converted into a new contact, account, or opportunity within Salesforce.com. This is really great. However, you may want, as in our example, to create an SObject type (like an Event) that's not allowed via a Lead or create multiple SObjects with one form.
- No programmers are needed for simple validation -- This may be incorrect, but my understanding is that Web2Lead provides no or only simple Javascript validation of form data. With PloneFormGen, you get to choose required fields and set simple validation (i.e. is this an email address, is this a valid telephone number, is the integer between X and Y, etc.). You're also using server side validation, which cannot be bypassed when a user disables Javascript in their browser.
- Adapters are addative - What if you want an email sent, a Salesforce object created, and the data to be saved within the ZODB. You can setup as many adapters as are needed for your form in question.
- The form is native Plone content, non-technical users can fiddle with the labels, ordering of form fields, add HTML formatted text proceeding the form, setup default values for fields, and more with the feature-set and ease-of-use offered by PloneFormGen.
What's next?
Well, we've already released an experimental version for testing. Time is always short, but the goal is to crank out a steady stream of minor improvements based on issues that arise from use of the product. Because we're integrating with a complex and powerful system in Salesforce.com, there are many both known and unknown bugs and features that are needed. Some of the known limitations include:
- We want to make sure that all of the form field data types work well with their logical Salesforce.com counterparts. For example, the date/time field doesn't currently work with Salesforce.com, as is exposed in my demo above.
- Lookups on existing Salesforce.com will require work to get right. Again, it would have been ideal, in my example, to populate the CreatedById field on the Event to create a relationship to the newly created contact, rather than de-normalize (if that's a word) the event by adding the submitted by email address.
- Required fields for the chosen SObject are not exposed in the Salesforce PFG Adapter UI. This requires a very deep understanding of a Salesforce.com configuration and the needed data types of fields you want populated with your PloneFormGen form.
With that said, when used in calculated cases, this is a very useful add-on Product for Plone. We'll be putting it through its paces on ONE/Northwest over the coming months and I'm thrilled to watch and help it improve.
July 17, 2007
Andrew Burkhalter: Plone & Salesforce.com: Using Salesforce.com as a Content Catalog
For those craving a bit more of a hands on update than my earlier background post on making Plone play well with Salesforce.com provided, hopefully this takes a step in the right direction. I'm going to be demoing the display of Salesforce.com content within the portlet of a Plone site. Credit to Jesse for helping me realize how dirt simple this is. Writing the code to do this took less than 10 minutes and that included asking a colleague a few questions about how exactly Salesforce.com works :)
The Use Case
Recently, the Executive Director of ONE/Northwest, Gideon, sent an email to staff emphasizing the use of quotes as a way to increase our credibility by allowing partners to tell our story in new potential partner circles. Being a nonprofit, think of a trusted grants manager quoted in a proposal to a new foundation or a donor quoted in our annual report. This also includes a quote about a completed web project appearing in our technology solutions section or a scope of work.
Even though we've had a Quote content type in our oft-internally-used, but not widely publicized Pigeonhole product, I thought I'd try an alternate implementation, which I see as very much complimentary, rather than competitive. For us, it makes sense to have our quotes coupled with Salesforce.com contacts. In other cases the ease and speed of doing Plone catalog lookups for related Quotes based on keywords is superior, especially as implemented in Pigeonhole as a lightweight content relation engine.
So, my colleague Steve had done some behind the scenes Salesforce.com fiddling allowing for the addition of a quote that's tied to a contact. I just added a new quote to my own contact record. See image below:

But, how would we display this and other quotes in a portlet on a local copy of onenw.org...
Beatbox Setup
If you're reading this post, I'm assuming you've got a working Plone 2.5.x instance lying around, which means you've got Python 2.4 as well. You may even have EasyInstall. If not, start here. Once you've met the basic requirements, you can install beatbox from the CheeseShop with:
easy_install-2.4 beatboxJust to prove this is working, fire up the interactive Python used by your Plone instance and type:
>>> import beatbox
Salesforce Base Connector Setup
Next you need to get salesforcebaseconnector
from the Plone Collective (hopefully we'll have a 1.0 alpha 1 release in the Plone Software Center
soon). Execute the following from your Zope instance's Products folder:
svn co https://svn.plone.org/svn/collective/salesforcebaseconnector/trunk/ ./salesforcebaseconnector
Upon restarting Zope, head to the ZMI and the Plone site where you'd like to talk to the Salesforce.com API.
Add a Salesforce Base Connector:

Select the radio button and hit "Add"


Enter information for a valid Salesforce.com account. This could be a free developer account.

The Code
I chose to do this in a Zope 3 view within the DIYPloneStyle-generated product, ONENWSkin, we use at onenw.org, but as mentioned in the previous post, an explicit goal for salesforcebaseconnector was to enable integrators to easily do the same in ZPT or a Python skin script that's not necessarily filesystem-based.
After the obligatory ZCML wiring, I created a file, browser.py, at the root of my product. The following import statements and the
"RandomQuotePortletView" class were all that was necessary:
from Products import Five
from Products.CMFCore import utils as cmf_utils
import random
class RandomQuotePortletView(Five.BrowserView):
"""Find recent job listings for portlet display
"""
def __init__(self, context, request):
Five.BrowserView.__init__(self, context, request)
self.sfbase = cmf_utils.getToolByName(self.context, 'portal_salesforcebaseconnector')
def getRandomQuote(self):
"""Returns a random quote from Salesforce.com in a dictionary
"""
res = self.sfbase.query(['Name','Quote_Text__c'],'Quote__c',"Usage_Guidelines__c!='Need to get permission'")
# res looks like a dictionary with a 'records' key
return random.choice(res['records'])
Of note, is the "query" method on our "portal_salesforcebaseconnector" object created at the site root in the setup above. We pass the query method a list of which fields ('Name' and 'Quote_Text__c' -- The '__c' convention signifies a custom field/object) we'd like to retrieve. The second parameter is our desired SObject, the custom Quote object, and finally we have an additional where clause which is based on our internal business rules of never showing any quotes where we don't yet have permission.
That's it! It's basically 2 lines of code (that could be collapsed into 1) within the contents of the "getRandomQuote" method and we're able to retrieve any and everything we might ever want from our Salesforce.com account.
Finally, we setup the following portlet, which defines the view, calls "getRandomQuote" on the view, and then displays the quote text for our randomly collected quote:
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
i18n:domain="plone">
<body>
<div metal:define-macro="portlet"
tal:define="view context/@@random_quote_portlet;
qDict view/getRandomQuote">
<dl class="portlet" id="portlet-quote">
<dt class="portletHeader">
<span class="portletTopLeft"></span>
Random Quote
<span class="portletTopRight"></span>
</dt>
<dd class="portletItem odd">
<span tal:replace="qDict/Quote_Text__c" />
</dd>
<dd class="portletFooter">
<a href=""
tal:attributes="href string:$portal_url/all-quotes"
>
More quotes…
</a>
<span class="portletBottomLeft"></span>
<span class="portletBottomRight"></span>
</dd>
</dl>
</div>
</body>
</html>
And after a few page reloads, to bypass the other quotes in our Salesforce.com instance, we see the following:

Conclusion
While I only demoed the use of the "query" call to the Salesforce.com API, you can skim the methods of the SalesforceBaseConnector class or read up on the API via Salesforce.com's APEX developer wiki for a better picture of what's possible. Note: Beatbox currently talks to the 7.0 version of the Salesforce.com API (several major version behind), so everything described in the docs may not be supported.For my money, this piece of the Plone and Salesforce.com integration landscape is probably the most ready for prime-time right now, due to the relative feature-completeness of Salesforce Base Connector. That is, if you ignore the lack of an official release :)
In the next few days, I plan to show off some work done to make PloneFormGen post directly to a Salesforce.com instance.
Jon Stahl: Varnish Supports Vary
If I understand this and this correctly, it means that Varnish now supports the Vary: header, which means that the last barrier to using this fast, easy-to-configure webserver proxy to front multi-lingual Plone sites should now be gone.
I also found a sample Plone/Zope config file for Varnish, contributed by Stig Sandbeck Mathisen. Cool!
According to Wichert, Plone.org is now using Varnish as its proxy.
Reading the tea leaves, it looks like a new generation of simpler, faster, easier-to-configure caching for Plone has arrived. Hooray!
If you've had experience implementing Varnish for your Plone site, please share your stories. I'm sure there are lots of folks who'd love to hear more.
July 13, 2007
Andrew Burkhalter: Making Plone play well with Salesforce.com
The first in a series of blog posts covering efforts in tightly integrating Plone with Salesforce.com
BACKGROUND
Every so often myself or Jon will get a batch of emails asking for the latest status on the Salesforce Connector, since our grant from the Salesforce.com foundation was originally announced in 2006. They always come in groups.
Externally, the product has shown little sign of movement for those that don't scour (and perhaps do...) the Collective Checkins list, which can be a great way to gauge what's active in the Plone community.
As a way to respond to those that have asked or are curious, I plan to post a series of several blog posts on The Plone Blog updating everyone on the latest.
Overall, the progress has been slow and arduous, but there have been a ton of
rewarding and committed conversations and discussion with the crew of us up in
Seattle (includes the talented Brian Gershon of The Web Collective and RagingWeb.com and Jesse
Snyder of NPower Seattle) that get together to hack on Plone and Salesforce.com
integration every Friday afternoons for "Open Source Friday's". Throughout this
all, a small, but interested community has formed, which is a key to ultimate
success in my opinion. Things are looking up.
THE FOUNDATION
Part of the original grant money went towards paying Enfold Systems to assess the status of and cleanup the beatbox codebase. It's a Python wrapper that talks to the Salesforce.com SOAP API written by Simon Fell, who was the original architect of the Salesforce.com API. Beatbox originally lived here, but has seen several homes throughout its life cycle and the active development is now happening at Google Code. (Drop any of us a line if you want to be involved in this project.)
I don't have a ton of insight into beatbox in and of itself, as I've not dug in too deeply, but it's now got a good suite of tests, thanks again to the Salesforce.com foundation and Enfold Systems and in our testing, development, and use of it we've added better support for various core Python data types and Salesforce.com SObject field types and exception handling that can be used within your applications.
It's hard to say how exactly this will evolve, but supporting the latest and
greatest Salesforce.com SOAP API (we're 2 major releases behind now) and putting
this code up as an Egg on the Cheese Shop are up there. The latter will hopefully
be done later this week. We'd be particularly open to help at this level of the stack ;)
BRINGING IT TO ZOPE
Thanks to NPower Seattle and one of its clients, we were able to dust off and extend a simple Zope product, salesforcebaseconnector, that merely manages credentials for a Salesforce.com instance, adds security, handles a volatile connection to Salesforce.com, and extends the Salesforce.com API to those that don't want to write filesystem code in unprotected Python space (i.e. browser views, tools, utilities, etc.) in order to import the need methods for talking to Salesforce.com.
Our primary ambition here is to make this easier for someone that's worked with the other toolkits provided by Salesforce.com that implement the exact same API methods. So even though things like "upsert" and "describeSObjects" might look foreign to a Python/Zope/Plone programmer, it should be comforting for anyone that's written code that talks to the Salesforce.com API.
This product will likely evolve fairly slowly (it's basically feature complete) going forward (there's always better test coverage, using Zope 3 appoaches, and keeping in line with the portions of the Salesforce.com API that beatbox supports) with the chance that we'll do a fairly disruptive name change before officially releasing this. We hope to bite the bullet and decide on this soon.
WHAT'S NEXT
Okay, so we've got these infrastructure pieces that work with our stack, what can we do with them? Stay tuned. Over the next couple days, I'll cover using this stuff to display desired data on your Plone site and a custom adapter we've got working with PloneFormGen.
Update:
<sarcasm>Jesse, Brian, and I sat down with the Open Source Friday marketing and branding team</sarcasm> and decided upon "salesforcebaseconnector" as the product name for the Zope wrapper to beatbox as mentioned in the section titled "Bringing It To Zope" above.
Naming is hard, but the "salesforce" portion should be obvious, the use of "base" suggests a developer/integrator focus, and "connector", as its primary focus is managing connections via the Salesforce.com SOAP API.
Finally, we intentionally chose to avoid mentions of various technical approaches (i.e. "tool" or the more modern "utility"),
which were included in the original naming. Our intention is at any time to support the 2 latest major Plone releases under a consistent
name, rather than allow proliferation of newly named products that implement various approaches for various Plone version. For historical releases, we'll
have releases and tags in the subversion tree. This is obviously easier said than done, but that's the goal.