Jaggery Apps that connect to Salesforce

Jaggery (What is it?) is a nice platform for creating web sites and mobile applications.  I’ve been using it to develop a portal application for WSO2 partners to use.  In that application, I use Salesforce as the data store for profile information about our partners, so I thought I’d show how simple it is to connect Jaggery to Salesforce with some example code.

Getting Credentials

First off, I create a little include file that contains the credential information for salesforce.  That way I can share the app, without sharing my credential information.  Here’s what the file looks like (appropriately anonymized):

salesforcecredentials.jag

<%
    // Salesforce logon credentials
    var salesforce_username = "jonathan@wso2.com";
    var salesforce_password = "mypassword";
    var salesforce_security_token = "mysecuritytoken";
    var salesforce_url = "mysalesforceurl"
%>

The username and password are assigned when you establish your salesforce account.  In Salesforce/Setup/My Personal Information there is a tab labeled “Reset My Security Token”.  This will send the security token to your email address and you can paste it into the above structure.  The url is found when at Salesforce/Setup/App Setup/Develop/API.  Select Generate Enterprise WSDL, save the resulting file, and scroll all the way to the bottom where you will see a <service> named SforceService, and with a soap:address with the url for your organization.  Copy and paste that into the structure above.  I’m one of our Salesforce administrators, if any of the above directions don’t match what you see ask your administrator for help.

Now you have all the information you need to connect so Salesforce, so lets’ see how to log in.

Logging in

I put the login function in it’s own import file so I can reuse it on any page that requires connecting to salesforce.  Here’s the code first, then I’ll walk through how it works.

salesforcelogin.jag:

<%
    include("salesforcecredentials.jag");
   
    var ws = require(’ws’);
    var salesforce = new ws.WSRequest();
   
    // declare the Salesforce typical namespaces
    var ns = new Namespace("urn:enterprise.soap.sforce.com");
    var sf = new Namespace("urn:sobject.enterprise.soap.sforce.com");
   
    // Login to salesforce.com, set up session, url, and options for subsequent calls
    function salesforceLogin() {
        try {
            // URL from the enterprise WSDL generated for us by Salesforce.com
            var options = new Array();
            options.useSOAP = 1.1;
            salesforce.open(options, salesforce_url, false);
            salesforce.send(
                <tns:login xmlns:tns="urn:enterprise.soap.sforce.com">
                    <username>{salesforce_username}</username>
                    <password>{salesforce_password}{salesforce_security_token}</password>
                </tns:login>
            );
            var loginResponse = salesforce.responseE4X;
   
            var sessionId = loginResponse.ns::result.ns::sessionId.toString();
            var serverUrl = loginResponse.ns::result.ns::serverUrl.toString();
            options.SOAPHeaders = [
               <tns:SessionHeader xmlns:tns="urn:enterprise.soap.sforce.com">
                       <sessionId>{sessionId}</sessionId>
               </tns:SessionHeader>
            ];
           
            return {
                sessionId : sessionId,
                serverUrl : serverUrl,
                options : options      
            }
           
        } catch (e) {
            return {error: e};
        }
    }

Jaggery allows you to declare and add modules, in this case I’m using the WSRequest object and so must declare it using the “require” function.  This gives me an object that is similar to the common XMLHTTP browser object but is specifically designed to make communicating in SOAP easier.  I’ll new up one of these objects called salesforce which we’ll use for communicating.

Note that I’ve declared salesforce globally, as well as declaring a couple of XML Namespace objects, we’ll talk about that a bit more later.  I can use these no only for logging in, but in subsequent calls to salesforce.  The login I’ve encapsulated as a function that can be called when  a login is required.

The first step is very simple, open the connection to salesforce, using SOAP 1.1 option and the URL we got from the Enterprise WSDL.  We’ll construct a payload requesting a login session and send it.  This part is pretty cool, as it makes use of E4X, which is supported by this implementation.

E4X, or Ecmascript For XML, adds XML as a native data type within Javascript, making querying and especially constructing XML a real snap!  You can see the basic syntax here – just write plain old XML, and use curly braces to insert values into it.  Here’s where we insert the username, password, and append the security token to the password field.  Couldn’t be simpler right?  Well the end result is pretty easy, but I manually trolled through the WSDL and the schemas embedded in it to discover the structures expected by the service – especially where the namespaces appear.  That can be a chore, and is the hardest part IMO of connecting to the service in this lean, write-the-message-yourself model.

Once you get the response back, handily parsed into an E4X XML object, it’s fairly easy to extract the necessary values.  In E4X you can navigate the XML tree structure easily using “.” notation, just like a hierarchy of Javascript Object properties.  However, there is a special syntax for namespaces, and the Salesforce return is full of them.  The notation requires that you declare a prefix (see the top of the example), and then use that prefix along with the awkward “::” to qualify the name.  I create this by printing out the whole return and writing each step of the query at a time to ensure I’m getting down to the right place.  If you’re new to E4X, but familiar with similar technologies like XPath, I recommend a quick read of the tips and tricks I wrote for the WSO2 Mashup Server documentation: E4X Quick Start Guide.

With the logon information in hand, in the form of a session id and a url for the service that will actually serve up my data, I can create some more E4X that represents the SOAP header required by subsequent calls to Salesforce.  I stick these prebuilt headers, the session id and the server url in a convenient object that subsequent calls can make.  Now we’re ready to actually get some data out of Salesforce!

Performing a Query

Here’s a function to look up information about a Salesforce Contact given an email address.  I’ve just included a few key fields, but you can add others at will – look up the field names in the WSDL, or even easier, in the Salesforce “Customize Object” editor.

<%

include("salesforcelogin.jag");

function contactDetails(email) {
    
    try {
        var contact = {
            email : email
        };
   
        var login = salesforceLogin();

        // Find the requested Contact account in Salesforce.
        salesforce.open(login.options,login.serverUrl, false);
        salesforce.send(
            <tns:query xmlns:tns="urn:enterprise.soap.sforce.com">
                <queryString>SELECT Id, FirstName, LastName, AccountId FROM Contact WHERE email=’{email}’</queryString>
            </tns:query>
        );
        var queryResponse = salesforce.responseE4X;

        contact.id = queryResponse.ns::result.ns::records.sf::Id.toString();
        contact.first = queryResponse.ns::result.ns::records.sf::FirstName.toString();
        contact.last = queryResponse.ns::result.ns::records.sf::LastName.toString();
        contact.accountid = queryResponse.ns::result.ns::records.sf::AccountId.toString();      

        return contact;

    } catch (e) {
        return {error: e};
    }
}

print(contactDetails("jonathan@wso2.com"));

%>

This should all look pretty familiar at this point – login, send a SQL query to find the requested data, and pull it out into a contact object.  In this case I’ll just print the results, which will return a JSON string from this page.

Setting values

One more example, pushing data back into Salesforce: the same login, open, send is all the same, but the payload indicates an update operation:

<tns:update xmlns:tns="urn:enterprise.soap.sforce.com">
  <tns:sObjects xsi:type="sf:Contact"
                http://www.w3.org/2001/XMLSchema-instance"
                xmlns:sf="urn:sobject.enterprise.soap.sforce.com">
    <sf:Id>{contactId}</sf:Id>
    <Assistant>{assistantName}</Assistant>
    <Title>{title}</Title>
  </tns:sObjects>
</tns:update>

Conclusion

I hope this post shows several useful aspects of Jaggery:

  • Specifically connecting with Salesforce
  • Using the WSRequest object to connect to SOAP services
  • How to leverage E4X to make constructing and querying XML easy and intuitive
  • Using import to promote reusable code fragments and simple data structures across pages

Now that I know it’s this easy to build interfaces to simple Salesforce data, I can imagine may other ways to leverage the vital data stored there across our organization.  I’m sure you can come up with some great ideas as well!

Please let me know if you have any comments or corrections – the above is based on the Jaggery 0.9 release.

What is Jaggery?

I’m excited about a new web application/web API development technology that WSO2 has been working on. Jaggery is a language for writing web applications, like PHP, ASP, JSP, and others.  These technologies are pretty well established, so why do we need another one?  I believe the demands of web applications have changed a bit over time and Jaggery offers a valuable refresh on web application development.

Javascript everywhere

A modern web application invariably includes a significant client-side Javascript component.  Being fluent in Javascript is a given.  Why then are we using a completely separate language for server-side programming?  It’s simpler to author when you don’t have to learn and then constantly switch your brain between two different languages.  Jaggery uses Javascript as the server-side programming language, the obvious choice for simplification.

As the client and web application have become closer, the distance between the web application and backend logic is increasing.  Backend logic that is typically written in Java or C# or some other “serious” language is increasingly exposed to a web application through web services rather through some direct integration.  Jaggery makes it fairly easy to access such services.

Sure, server-side Javascript isn’t really new – I’ve used ASP with the <% @Language=JScript %> switch for many years with Microsoft IIS, but Jaggery brings this option to the forefront and jumps the chasm to the Apache web server community.

JSON everywhere

Modern web applications typically make heavy use of native Javascript Objects as a data model.  This is driven not just by the convenience of writing, navigating, and manipulating Javascript objects, but by the convenience of JSON to communicate between the client and the server.  AJAX in practice is now AJAJ: Asynchronous Javascript and JSON.  (But AJAJ is just too hard to pronounce, most people continue to say “AJAX”.)

When the communication between client and server are largely JSON, server-side programming that gracefully supports JSON is a huge simplification.  I for one am pretty tired of investing most of the lines of server-side code in simply getting XML or some other format into and out of JSON.  Jaggery of course can convert JSON to Javascript Objects, explicitly as well as automatically in some cases, but being able to use native Javascript Objects on the server is another great motivator to use Javascript as the programming language.

Web site/Web service

Sites that just serving up HTML are becoming increasingly rare.  Rich user experiences demand AJAX, mobile applications, and third-party integration.  These services are increasingly offered as HTTP/JSON services.  Jaggery makes it as easy to develop fully RESTful web services as web pages.  It gives you full access to the HTTP method, the requested content type, status messages, and so forth, to support the pattern of the URI identifying an abstract resource, which can be manipulated in a variety of ways (GET, PUT, POST, DELETE) and returned in a variety of representations (HTML, JSON, XML).

helloworldHello M€mb€r of th€ Financia£ €£it€$

Enough chatter – here’s a simple example, a step beyond the basic Hello World to help you get a sample of Jaggery’s joys, showing both dynamic html generation, JSON generation, and AJAJ linking the two to enable dynamic page updates.

<%
    //this url can return either json or html
    var accept = request.getHeader("Accept");
    if (accept.indexOf("application/json") >= 0) {
        // return json
        var change = parse(request.getContent());
        print({
            name : change.name,
            leet : change.name.replace(/[sS]/g,"$")
                              .replace(/[eE]/g,"&euro;")
                              .replace(/[lL]/g,"&pound;")
        });
    } else {
        // return html
        var name = "M&euro;mb&euro;r of th&euro; Financia&pound; &euro;&pound;it&euro;";
%><html>
    <head>
    <script src="
http://code.jquery.com/jquery-1.8.2.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function(){
            // install a handler whenever the newname changes
            $("#newname").change(function(event){
                // HTTP post with application/json request type
                $.post(    "helloworld.jag?api",
                    JSON.stringify({ name : $(this).val() }),
                    function(data) {
                        // update html fields with JSON returned from the server
                        $("#name").attr("title", data.name).html(data.leet);
                    },
                    "json"
                );
            });
        });
    </script>
    </head>
    <body>
        <h1>Hello <span id="name"><%=name%></span></h1>
        <p>My new name is <input type="text" id="newname"/>.</p>
    </body>
</html>
<% } %>

Try it out

There are many other details and ideas that are in Jaggery or under consideration.  While Jaggery had its inception at WSO2, and is supported in the current release of the WSO2 Application Server, the specification and an implementation are all open source and we invite others to contribute, use, and even develop alternate implementations of this technology.

Visit http://jaggeryjs.org to download the latest release (alpha at this writing) and give it a spin.  Join the conversation – what areas of web application development haven’t kept up with the times?  Addressing those is what Jaggery is all about.

I plan to blog occasionally about both the sweet areas, as well as look more deeply into areas that require some improvement. You can follow just Jaggery posts by subscribing to http://jonathanmarsh.net/category/jaggery/.

Canyon Edge Concert, Aug 18th

Jason and I are putting together a formal house concert on Aug 18th 7PM here at our home on the North Fork.

IMG_0689psGrand piano, violin, keyboards, octave violin, maybe even some tablas - we’re planning to go all out with new material! Come listen as we orchestrate an accompaniment to nightfall over the canyon, mixing electric and acoustic, modern and folk, planning and improvisation into a unique musical event. And we’ll even top it off with dessert!

The concert will start at 7PM at our home at 3144 Manhattan Bar Road in Auburn.  Reservations will be required as we’ve a limited amount of space. – contact Genevieve at 916-316-8061 or gmarsh@risd.edu, or visit risd-artcar.webnode.com/donations to reserve.  All donations go entirely to an excellent cause - topping up the Project Pinwheel budget in its final hectic weeks of construction.

We’re looking forward to seeing you and your friends on the 18th!

Check out Jason Marsh’s Digital Acoustic Violin

Jason Marsh: Digital Acoustic Violin

Jason Marsh: Digital Acoustic Violin

It’s been out for a few months now, but if you haven’t heard Jason’s new Digital Acoustic Violin album, or checked out his YouTube video showing that yes indeed, each piece is a single live take, then you’re missing something incredible.

Get it at http://jasonmarsh.bandcamp.com/album/digital-acoustic-violin.

Jonathan’s Chai Tea Latte

CIMG9840psOur standard here in planet Starbucks is Oregon brand Chai concentrate.  But I find it a little cloyingly syrupy, over weighted on the cloves, and just not very complex in flavor.  But some of the more traditional Indian recipes are a bit over-weight on ginger (many use pungent fresh ginger) and rather too aggressive for a soothing cup.  So I’ve been evolving a recipe that matches my taste better.  Come share a cup with me or try it yourself!

Whole spices:

  • 1 4” cinnamon stick
  • 8 cardamom pods
  • 6 cloves
  • 4 black peppercorns
  • 1/8 t fennel seed

Ground spices:

Other:

  • 4 cups water
  • 1 t vanilla
  • 5 T brown sugar
  • 3 T loose leaf black tea (I use a good Sri Lankan Orange Pekoe or Broken Orange Pekoe)

Put the water, brown sugar and vanilla on to boil.

Break up the cinnamon stick as much as possible, and toast in a small skillet with the cardamom, cloves, and peppercorns until quite fragrant, maybe even on the edge of smoking.  Add the fennel seed and continue toasting while the fennel seeds quickly brown.  Grind the lot in a spice grinder, then toss in with the liquids.

Cooling the skillet a bit, toast the ginger, nutmeg, and rice powder until just starting to brown.  Toss in with the liquids.

Finally, when the liquid starts to boil turn off the heat and add the tea.  Steep for about 5-7 minutes.  Strain thoroughly (I use two progressive steel meshes) into a bottle, which I cool and keep in the fridge.

To serve, mix the chai elixir with an equal quantity of milk and heat (usually nuke) till scalding.  Makes about 8 cups.  Top with a froth of foamed milk and cinnamon dust for special occasions!  Or blend 2 parts with 1 part ice and 1 part milk for a Chai smoothie.

The end result should taste noticeably but not overwhelmingly sweet with hints of vanilla and a general toasty flavor without any other ingredient dominating.  You may need to adjust the mix depending upon the origin of your spices or to meet your liking.

Hope you enjoy!

Christmas Night

I recorded a bit of improvisation around some familiar Christmas tunes for the holidays. Enjoy!

 
icon for podpress  Christmas Night [10:25m]: Play Now | Play in Popup | Download

Need a YouTube soundtrack?

I’ve been using pieces from Off the Path and Dry Hot Long Ago as soundtracks to YouTube videos I post for my wife Deanna, such as this one:

Visit http://deannamarsh.com/category/video/ for more videos.

I’ve also started getting requests from other artists for licenses to use the music in their videos.  Such as this one from Grant’s Pass artist Randy Johnson:

More about Randy at http://www.johnsonartworks.com/.

I think the character of the music fits really well with art videos – adds some gentle emotion but doesn’t detract from the art.

Artists should be well versed with intellectual property (as they create it every day) and it’s wise to have permission to use the material you publish – even background music.  So contact me if you’re producing a promo video – I’m much easier to deal with for a license than a record label ;-).

Five don’t-miss things at WSO2Con 2011

I’m about to leave for Sri Lanka, to attend WSO2Con 2011 in Colombo.  What am I looking forward to most?  I tend to favor stories of the practical!

1. Sastry Malladi, Distinguished Architect at eBay.  Sastry was instrumental in eBay’s choice of WSO2 ESB which is now handling about a billion transactions a day.  This has been a great case in ultra-scale applications and how SOA helps with this.  Sastry is full of wisdom on practical SOA.  Wed at 9AM Sastry gives the keynote on “Service Orientation: Why it is good for your business.

2. Brad Svee, Senior Manager at Concur.  Concur uses WSO2 as a strategic platform for their enterprise and Brad is one of our earliest customers – lots of great experience to share!  Tue at 12:15PM Brad speaks on “Delivering the Goods: Automated Quote to Cash.”

3. Thilanka Kiriporuwa, Head of HR and Operations at Odel.  Odel has put in place the leading leading edge of retail, familiar to Apple Store aficionados – a wireless iPod credit-card processor.  Swipe and purchase without waiting in a cashier’s line.  Tune in Wed at 15:30 for “Building a Mobile POS Solution with WSO2 Carbon and Apple iPod Touch.”

4. Paul Fremantle, WSO2 CTO.  Always love Paul’s thinking and there’s always insightful nuggets.  Paul gives the closing keynote Thu 16:15 on “WSO2 Vision and Roadmap.”

5. A Sri Lankan cultural show on the evening of the 13th – traditional music, dances, and slinging fire around.  Should be great fun!

Hope to see you at WSO2Con!  And don’t forget to tweet with #wso2con for a chance to win!

Vibrant Earth

P1030495I’ve been helping Deanna install and promote her first museum show, at the Grants Pass Museum of Art.  About 25 large pieces representing a year of creative output.  Quite impressive.  And an extensive installation project!

If you can’t stop by, you can see a little youtube of the installation and opening night here.  And more details and photos will be coming soon to deannamarsh.com.

Monkeys

Monkey laneNice hairdo

Just uploaded a backlog of Sri Lanka photos from my last trip – six months ago already!  The trip included an offsite at a beach hotel, a weekend trip to Sigiriya and other ruins, and encounters with dozens of furry monkeys.  See the photoset here.

Lost Coast – Found!

UrchinTook a few days during spring break last week to backpack California’s Lost Coast with my daughter.   Flickr set here.

The Lost Coast is in the far north of California, roughly between Mendocino and Eureka.  It’s characterized by such rugged and shifty geology that Highway 1 abandons it’s coastal route and heads inland around this section.  Backpacking (mostly on the beach) is the primary access to this coastal wilderness – a rarity of which Shi Shi Beach is one of the only other examples in the continental US.

Wood, Stone, SeaWe arranged a shuttle from Shelter Cove to Mattole Beach (quite a scheduling and financial effort) and arrived at about 7PM on Sunday night, in gentle but insistent rain.  We decided to get a mile under our boots before nightfall, and headed off.  As darkness fell, we pitched the tent and cooked up some dinner before a long and soggy Misty fallsnight during which the rain continued to fall, condensation dripped on us, and puddles formed under our sleeping bags.  But the rain stopped at about 6AM and we struck off again early to warm up.

We had a scrumptious breakfast of breakfast burritos perched on the roof of an abandoned lighthouse – Freeze-dried Mountain House Eggs/Ham/Peppers on a burrito with taco sauce.

Poppies on the cliffThroughout the morning the fog and clouds lifted and by about noon the sun came out.  We scrambled over bluffs, along rocky beaches, and forded rivers.  Wildflowers were out in profusion – California poppies, lupine, wild parsnip, irises, and lots more.  A long lunch break allowed us to dry our gear.

High tides were about midday, and although many stretches are deemed “impassable” on the map, there were only a few times we had to race the waves or scramble over scree to keep going, even though the strip of beach can be pretty narrow between the waves and the cliffs eroding practically before our eyes.

Surrounded by foamOver the course of the next few days we saw many sea lions, river otters, seagulls and cormorants, racoon and deer prints on the beach, tidepool life, and even whales, all thriving in the wilderness outside the influence of man.

Because of some road closures we weren’t able to complete our planned section south of Shelter Cove to Needle Rock but instead looped around to Usal Beach anNot dodging the waved hiked the bluffs at the southern end of the Lost Coast.  Total of about 30 miles in 4 days.

Just as the rain started to hit again we finished and headed to Fort Bragg for a cheap motel, hot showers, cioppino, and a movie.  Civilization isn’t all bad either.

Would love to go back and do the whole 60 miles end-to-end!  But not looking forward to even more complex shuttle logistics. 

All worth it to see Gen’s smiles ;-).

Triumph

Mid-story Hong Kong skyscrapers

Midstory 9

Spend my traditional one-day layover in Hong Kong with camera in hand.  The relatively chilly day proved perfect for a longer walk than usual through the downtown area followed by a hot bowl of noodle soup.  What intrigued me this time was the density and variety of skyscrapers, and some of the stunning geometric patterns that result from this reflective urban landscape.

I stayed away from ground shots (the understory) though you will see a couple of lively shots.  Nor did I attempt the the skyline (the canopy) which was difficult with the poor lighting conditions.  But instead I focused on the mid-story, those canyon walls we tend forget to notice in the street-level jumble of activity, but which reward the alert with a nice abstract art show.

Midstory 14

Midstory 17

View the whole set here.

Blue Seattle

A quick trip to Seattle for Thanksgiving and in particular a visit to the Space Needle in the dusk resulted in some strange abstract photos – the combination of snow and dusk and a clear, incredibly deep blue sky, and the unavoidable railing slicing the photos into a grid.

Blue Seattle Abstract 4

That of course is Frank Gehry’s whimsical Experience Music Project building…

Blue Seattle Abstract 3 

See the complete Blue Seattle photoset on Flickr, along with some cold beach shots from Cannon Beach.

“Dry Hot Long Ago” now available on CD

DHLAcd The first pressing just arrived and it looks great!  The perfect Christmas gift for your over-stressed friends and business associates.  See the web site for ordering information.

Dry Hot Long Ago goes live on iTunes!

After many months in final production, my album Dry Hot Long Ago has finally appeared for sale on iTunes! Amazon downloads and direct CD purchases will be coming soon.

This album continues the solo piano improvisation tradition started in my first album Off the Path, but for me evokes not just the natural world, but the landscapes of memory, nostalgia, and change.  It represents continued growth in both the sophistication, and the simplicity, of my work.  I’m sure you’ll like it!

Please leave a review or rating on iTunes and spread the word!