You need to sign in to do that
Don't have an account?
Jumping through the Namespace hoops
Here's one for all you builders of managed packages. I wanted to place a Custom Button the on Accounts page that you recalculate a value. To do this I needed to call a class, this can be achieved by setting the Custom Button to call some Javascript and then wire up an Ajax call. The code is straightforward
{!REQUIRESCRIPT("/soap/ajax/21.0/connection.js")} {!REQUIRESCRIPT("/soap/ajax/21.0/apex.js")} var bal = sforce.apex.execute("PaymentEngine","getAccountBalance", {id:"{!Account.Id}"}); //more code
The class needs to be Global and the method static and prefixed with WebService. All good.
HOWEVER if this is App is converted into a managed package the call will fail as the class requires that it has the Namespace prepended to it. The Ajax Toolkit allows you to add the Namespace via sforce.connection.defaultNamespace ="myNamespace". But I have to know the namespace in the first place. Moving between dev, deployment and product orgs it is not feasible to do this. Inspired by this article I created the following:
{!REQUIRESCRIPT("/soap/ajax/21.0/connection.js")} {!REQUIRESCRIPT("/soap/ajax/21.0/apex.js")} var result = sforce.connection.describeGlobal(); var TOKEN_OBJ = "Patient__c"; //ensure we get our Apps Namespace not someoneelses var sobjects = result.getArray("sobjects"); var ns = ""; for(var i=0; i<sobjects.length; i++) { var sobjName = sobjects[i].name; //sforce.debug.log('Object Found: ' + sobjName); //describeResult = sforce.connection.describeSObject(sobjName); //dont call this makes it reallt slow // sforce.debug.log('Is Custom: ' + describeResult.custom); var str = sobjName.split("__"); //if there are 3 values there is a namespace if (str.length == 3){ sforce.debug.log(sobjName + ' has namespace'); //Is it one of ours? var sobj = str[1].valueOf() +'__c'; if(sobj == TOKEN_OBJ) { ns = str[0].valueOf(); }else{
// just for debugging and testing
// sforce.debug.log(sobjName + ' is not in my namespace'); } }else{
// sforce.debug.log(sobjName + ' has no namespace'); } } if(ns != ""){ // sforce.debug.log(('I have a namespace called ' + ns');
sforce.connection.defaultNamespace =ns; }else{ // sforce.debug.log(('I have no namespace called'); } //now do stuff var bal = sforce.apex.execute("PaymentEngine","getAccountBalance", {id:"{!Account.Id}"}); window.alert("Balance updated to: " + bal );
So it works, but its crazy. Please Mr Salesforce can you make it easier to get the Namespace via AJAX, Javascript, jQuery. How about sforce.connection.getNamespaceFor('MyCustomObject__c');
Here's a further refinement
The sforce.apex.execute requires a . notation and the field a __ so this ensures the syntax is correct. I got failures in a managed package even though the namespace was set in default namespace
All Answers
It's an interesting use case - and that's pretty clever solution. I'm not sure what the update schedule is on the AJAX toolkit, but I'll poke around and see if we can add in a more utilitarian function.
Out of curiousity, have you seen any of the JavaScript Remoting being released in Summer '11? It might save you the API call.
I've read through the stuff on remote scripting but didn't see anything special concerning namespacing, so didn't go much further. Still it, looks like there is some interesting stuff in it.
In general we're using a lot of jQuery and extensive use of the Ajax toolkit so the inability to get access to the namespace is a bit of a headache. We have been using a custom setting to store the Namespace value and then setting a property on the custom/extension controller to get the value. We'd then use property value as a field merge
This worked fine, even if its hack, until today when I wanted to add a custom button to the standard Accounts page.
We'd be more then happy to share code, use cases and assist in anyway we can
Just to round this off. Here is the final code:
Notice the syntax used to get the Account_Balance___ field to update. 'account.account_balance__c' worked fine in the unmanaged packaged but failed in the managed package. At first I thought the issue was related to the namespace so I tested with the Name field - but this failed as well. One of our other developers encountered the same issue and realized that using an array syntax would work i.e. account[ns+"CustomField___c"] ='abc';. For standard fields omit the ns (account["Name"] = 'abc';). Make sure you declare the namespace variable ns as an empty string.
Here's a further refinement
The sforce.apex.execute requires a . notation and the field a __ so this ensures the syntax is correct. I got failures in a managed package even though the namespace was set in default namespace