Simon Fell > Its just code > February 2007

Wednesday, February 28, 2007

In between the thunder and lightening the other night, there was the mother all hail storms, I tried to get some pictures.

Tuesday, February 27, 2007

Teme blogged the details of the Mazzer doser sweeper mods, I saw this this ages ago, but only got around to trying it out on the Major this weekend, its an impressive improvement, there really is no grinds left in the bottom of the chamber, next time I won't take so long to try it out. I wonder how long it'll take Mazzer to start fitting some kind of rubber skirt on the sweeper vanes in the factory ?

Friday, February 23, 2007

Somehow there's a console war, yet 2 out of the 3 consoles are almost impossible to actually buy, not much of a war when only one side turns up. I've been after a Wii all week after playing Wii Boxing at a friends, WalMart actually claims to have some in stock, if you'll plunk down for the $600+ bundle, not only that, but watch-out for the $200+ shipping charges, whoa, WTF. ??

Wednesday, February 21, 2007

Trapdoor v1.1 is out, if you have v1.0 installed, next time you run it, it'll ask if it should update itself. (or hit check for updates in the menu). It now picks up Keychain events and updates its list of credentials, so if you add a new login via Safari, or you use Keychain access to remove a Keychain entry, Trapdoor will update the Login list straight away. If your Salesforce.com password changes after you've added it to trapdoor, next time you try and use it, it'll tell you the password is no longer valid, and prompt you for a new one, it'll then log you in and update the keychain entry. Finally Tomasz Oczapowski sent me a good idea, which is to allow you to set an alias for each login, and to show that in the login list, here you can see that in action, I added a 'DE edition org' alias for one of my logins.

The alias is stored in the comment field in the keychain entry, and you can enter the alias on the new credentials window, but if you want to add alias's for your existing keychain entries when you upgrade, just use the Keychain Access utility to add your alias's to the comments field.

Tuesday, February 20, 2007

I got a read-only filesystem up and running :)

Its a real filesystem, so things like preview in finder work, you can double click a file to launch it in its associated app, you can drag'n'drop to other drives on your system etc.

If you want to try it out, you need to install MacFuse first, then unzip sfdcFuse and run

sfdcFuse username password
, it'll verify your credentials, check you have access to documents and folders, then say
Logged into Salesforce.com successfully, about to mount Volume. (This program will exit when you eject the volume)
, at this point the SalesforceDocuments volume should appear on your desktop. Let me know how you get on.

Monday, February 19, 2007

I mentioned a while back that I wanted to try out MacFuse, I've been tinkering with it over the weekend, still got a ways to go, but made some nice progress, I now have a mounted directory structure that mimics the structure in Salesforce.com.


grooverider:/ simon$ ls -l /tmp/sfdc/Test\ docs/
total 1456
-r--r--r--   1 simon  simon  694842 Feb 19 15:58 soqlx.jpg
-r--r--r--   1 simon  simon   49730 Feb 19 15:58 wsCalls.pdf

Props to Jonathan Wight for the Objective-C wrapper for MacFuse.

Sunday, February 18, 2007

SoqlX and SF3 were the first OSX / Salesforce.com app I wrote, both use the keychain (despite their being no cocoa api for Keychain), however I modeled the Keychain interactions on Camino, and at some point back I realized that's a bad model, as it assume one keychain entry per "thing". As Trapdoor shows, this is clearly not the case, and so I've been working on a replacement login process for my apps. In the process I also realized that getting all of it right and usable is actually a fair amount of work, managing multiple login servers, multiple keychain entries per server, creating and updating keychain entries, interaction with preferences etc, it all adds up. So I also built it as a standalone controller class and nib, so that i can easily re-use it across more apps. I just released a new build of SoqlXplorer, which has this new login code in it, along with support for the new queryAll call. If you have any interest in seeing the login / keychain controller & nib, let me know.

Saturday, February 17, 2007

Documentation on writing Quicksilver plug-ins is thin on the ground, I mainly used a combination of this tutorial, the source for the Sherlock Channel plugin, and looking at the plists of the various plug-ins i have installed. And now Vacuous Virtuoso is running a tutorial series.

Tuesday, February 13, 2007

They say a picture is worth a thousand words, here's a couple of quick movies of the Quicksilver plug-in in action.

My previous ramblings about Spotlight left me thinking about a Quicksilver plugin, I use Quicksilver way more than Spotlight, plus Quicksilver is extensible (if poorly documented) with additional plug-ins, so I put together a Quicksilver plug-in for Salesforce, download the plugin, expand the zip, double click the plugin file to install it into Quicksilver, then goto the Quicksilver properties to setup your Salesforce login info. After that, there's 2 new actions, the first is search, associated with QS's text mode (e.g. hit ctril-space to bring up QS, hit ., type foo, tab to the action menu and select search salesforce, takes 10 times longer to explain than to do). The 2nd action is associated with files, and allows you to easily upload a file into a document in Salesforce.com. Feedback welcome over on the MacForce list.

Monday, February 12, 2007

As I mentioned way back in April 2003, wsdl.exe /server is basically useless. This is fixed in .NET 2.0, and wsdl.exe /serverInterface works pretty much as you'd expect (or at as I'd expect, which is good enough for me). If you're trying to use the new Outbound Messaging feature that was part of the recent Winter release, and you're still on .NET 1.1, then you'll run into this real fast. For those who haven't seen the feature, basically you specify some condition to send you a message, you define what fields you want in the message from the target object, and we generate a WSDL that represents the messages we'll send you. You feed this wsdl into your tool of choice to spit out your server skeleton, and off you go. Well, unless you're on .NET 1.1, where its not remotely obvious what to do. So, here's a quick guide to getting up and running with Outbound Messaging and .NET 1.1.

  • Stop, why are you still on .NET 1.1? are you sure you can't move up to 2.0, you should seriously investigate this first.
  • Ok, if you're still here, go into the Salesforce.com app, setup, workflow and setup your rule and outbound message, in the message pick the fields you want (I picked the Contact object and the firstName & lastName fields).
  • Right click on the "Click for WSDL" link, and save it somewhere.
  • From the command line, run wsdl.exe /server om.wsdl to generate the stub class and types file (it'll be called NotificationService.cs by default)
  • You'll notice that the generated class is abstract, but don't fall for the trick of creating a concrete subclass, its not going to work.
  • Horrible as it is, the easiest way forward is to now modify the generated code, remove the abstracts, and add an implementation to the notifications method, here i'll just copy the contact objects to a static list so i can have another page view the list of contacts i've received.
    [System.Web.Services.WebServiceBindingAttribute(Name="NotificationBinding", Namespace="http://soap.sforce.com/2005/09/outbound")]
    [System.Xml.Serialization.XmlIncludeAttribute(typeof(sObject))]
    public class NotificationService : System.Web.Services.WebService {
        
        /// 
        [System.Web.Services.WebMethodAttribute()]
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", 
    		Use=System.Web.Services.Description.SoapBindingUse.Literal, 
    		ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
        [return: System.Xml.Serialization.XmlElementAttribute("notificationsResponse", Namespace="http://soap.sforce.com/2005/09/outbound")]
        public notificationsResponse notifications(
    		[System.Xml.Serialization.XmlElementAttribute("notifications", Namespace="http://soap.sforce.com/2005/09/outbound")] notifications n) {
        	foreach(ContactNotification cn in n.Notification) {
        		lock(objects) {
        			objects.Add(cn.sObject);
        		} 
    	}
    	notificationsResponse r = new notificationsResponse();
    	r.Ack = true;
    	return r;
        }
    
        private static System.Collections.ArrayList objects = new System.Collections.ArrayList();
        
        public static System.Collections.ArrayList CurrentObjects() {
        	lock(objects) {
        		return (System.Collections.ArrayList)objects.Clone();
        	}
        }
    }
  • Next up you need to compile this into a dll, run csc /t:library /out:bin/om.dll NotificationService.cs (this assumes you've already created the bin directory that asp.net needs). Now you can wire it up as a webservice, you can do this by editing the web.config to map a URI to the class, or just use a dummy asmx page that points the class, that's what i did, here's om.asmx
    <%@ WebService class="NotificationService" %>
  • At this point you should be able hit hit the asmx page with a browser and get the regular .NET asmx service page.
  • Next, we'll add a simple aspx page that can access the static objects collection and print out the details from the messages it got. (obviously a real implementation should do some real work in the notifications method, but this is a handy test)
    <%@ Page language="C#" %>
    <html><head>
    </head><body>
    <h1>Recieved Contact ids</h1>
    <%
    foreach(Contact c in NotificationService.CurrentObjects()) {
    	Response.Write(string.Format("{0} {1} {2}<br>", c.Id, Server.HtmlEncode(c.FirstName), Server.HtmlEncode(c.LastName)));
    }
    %>
    </body></html>
  • That's it, go into the app, trigger your message, and refresh the aspx page to see the data from the message we sent you.

A slightly cleaner approach is to actually do the subclass, and to copy over all the class and method attributes to the subclass as well, at least then you can easily re-run wsdl.exe if you need to (say if you changed the set of selected fields).

Sunday, February 4, 2007

Congrat's to Charlie & Crew on the public beta for SpanningSync, I did some tests using SpanningSync with SF3 to 3 way sync iCal / gCal and Salesforce.com, and so far it works great. If you want to use this combo, I'd recommend you turn off the timed sync in SF3, as it'll auto join the regular sync sessions that SpanningSync kicks off. Of course, letting 2 beta programs mess with your data at the same time is likely to end in tears, make sure you have a good backup.

Saturday, February 3, 2007

One of the first Salesforce.com integrations I wanted to do on the Mac was to plug-in to Spotlight. However the official way to extend Spotlight, it to add your own metadata importers, however this basically requires you to have files on the local filesystem, there's no way to plug-in into the actual query runtime and run additional queries against external data sources. (I wonder if this is planned for Leopord or not?). So, for the Salesforce.com integration, this would mean pulling down all the data you wanted spotlight to index down to the Mac, certainly doable, but smacks of using a sledgehammer to crack a nut. Someone on the Idea Exchange mentioned a Google Importer, which adds Google searches to Spotlight, but as far as i can tell, it does it by using an InputManager hack to inject itself into the spotlight UI, sounds like you'd end up spending all your time fixing it up as the internal details of Spotlight changed.

None of the existing forums seem to have a suitable area for Mac/Salesforce users, so I started the Macforce group on Yahoo.