6

How can I get organization's namespace prefix through API?

This solution doesn't match because it's not supposed that I know anything about org classes.

I understand that I can query ApexClasses through Tooling API, than create set and get all namespace prefixes BUT in that case I have to query also ApexTriggers, ApexPages and everything that can have namespace prefix.

Is there any better solution?

  • 1
    What problem are you trying to solve? – sfdcfox Dec 17 '14 at 17:38
  • I'm creating a small application and I need to know a namespace prefix of an org. At the moment I would not like to talk about my app :) – Liudmila Likhovid Jan 13 '15 at 11:25
2

The DescribeMetadataResult from the Metadata API provides this in the organizationNamespace field.

There is an Apex wrapper for the Metadata API up on Github: https://github.com/financialforcedev/apex-mdapi that should give you access to the data you need (https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataService.cls#L238)

  • Thank you! I just wonder, is it a recent change to DescribeMetadataResult or it was for a long time? – Liudmila Likhovid Jul 14 '15 at 13:47
  • 1
    Not sure when it was added, but looking at the API documentation it was available in v29 (Winter '14). The on-line documentation doesn't go back further than that so I can't tell you for sure when it was added. – Mark Keats Jul 15 '15 at 7:35
13

Spotted in the Spring `16 release notes under Changed Objects:

Organization

The following new fields have been added:

  • NamespacePrefix
  • SignupCountryIsoCode—Represents the two-character ISO country code specified by the user for a sign-up request.

It appears it will now be possible to directly query for the NamespacePrefix using SOQL

string np = [SELECT NamespacePrefix FROM Organization].NamespacePrefix;

So it should be easy enough to run this through the REST or Partner API. Just make sure your API version matches at least the Spring `16 release.

  • Wouldn't this only be applicable in the packaging org itself? I doubt it would be context aware based on the managed package which is querying this field. – Mark Pond Dec 21 '15 at 18:04
  • @MarkPond I assume it would only get the value for the current org that the code is running on. This would apply equally to local code and code from a managed package. It's so new I haven't had a chance to test it yet. – Daniel Ballinger Dec 21 '15 at 19:06
  • No problem. If it's context-aware, that would be magical. – Mark Pond Dec 21 '15 at 19:20
  • I tried creating a package foo with a method that would resolve the namespace with that query. The unit test which tests whether the resolved namespace is foo passes as the package is installed. Calling the global method from the foo package however returns null instead of foo; the namespace of the current org, not the packaging org. – ipavlic Feb 15 '18 at 15:00
  • 1
    @DanielBallinger I'm just confirming the behaviour. – ipavlic Feb 16 '18 at 1:14
3

How about using the Tooling API to execute Apex:

public class MyClass {}
System.assert(false, MyClass.class.getName());

This would create a class in anonymous context just long enough to throw an exception with the fully qualified name, which you could read from the result body.

  • Nice idea. I tried it with Spring 15. It's giving me a GACK due to the inner class. 202766208-43981 (-1286861626) – Daniel Ballinger Apr 30 '15 at 22:30
  • @DanielBallinger works for me :D :D with no semicolon after the class... – bigassforce May 1 '15 at 23:19
  • I tried again, this time using execute anon in the developer console. (I'd also found the extra semicolon on the inner class). In my Dev org with a namespace I get a NullPointerException from MyClass.class.getName() unless I prefix it with the orgs namespace. I.e. DFB.MyClass.class.getName(). – Daniel Ballinger May 3 '15 at 9:00
2

You can lean on the System.PageReference API to help a little bit with this:

//gives eg "/apex/ns__apex/"
String qualifiedUrl = new PageReference('/apex/').getUrl();

//gives eg "ns"
return url.substringBefore('__').substringAfterLast('/');

Execute him from unmanaged Tooling API context to guarantee it works.

1

Query the Metadata API and fetch all of the InstalledPackage metadata type. That will tell you the namespaces of each managed package installed in the org as well as the version number for each package.

You can do a bulkRetrieve from the Force.com Ant MIgration Tool:

<sf:bulkRetrieve username="${sf.username}" password="${sf.password}" metadataType="InstalledPackage" retrieveTarget="installedPackages"/>

Here's a full example using this approach to parse the returned files and return the version of a specific namespace: https://github.com/SalesforceFoundation/CumulusCI/blob/master/build/cumulusci.xml#L67

1

Please use the solution from bigassforce provided as a different answer and here How to get the DE-Orgs Namespaceprefix? (NOT the Namespaceprefix from the scope of an object or class) - the following is my old approach which for now works too, but I can not recommend it.

This is a tough nut to crack and I found only an ugly and hackish solution which requires high user privileges.

It seems that there is no clean direct method provided by the APIs to get the Org's Namespaceprefix. To clarify: we are NOT looking for a prefix from the scope of an installed managed package. Instead we are looking for the namespaceprefix which the org is providing. That means it's only existent in Developer Editions - never in Production environment. But if you create Apps, which might be installed in Dev-Orgs and Production Orgs and you don't I and have to deal with it dynamically you need to determine which is the prefix of you residing org. Again NOT the one from within which your doing the determination.

My workaround is - sadly and only out of frustration - to fetch the setup-page and parse the html-body for it. It might break, if Salesforce updates the setup.

This said, here comes my workaround:

public static string getOrgNamespacePrefix() {
    string result = '';
    string[] tds = new string[]{}; 
    PageReference p = new PageReference('/0A2');
    String html = '';
    if(!Test.isRunningTest()) { html = p.getContent().toString(); }
    html = html.replace('\r','');html = html.replace('\n','');
    xr r = new xr ('<td class="summaryYes">(.*?)</td>',  html  );
    // there are 0 to 3 matches, BUT only if there are exactly 3 matches, the third one is the namespace! 
    while(r.find()) {
        tds.add(r.group(1));
    }
    if(tds.size()==3) result=tds.get(2);
    return result;    
}

with xr is only a wrapper for ease+convenience around standard regexp (you can get rid of it, if you don't like it just by replacing it.

public without sharing class xr {
    public static xr build(string regex, string haystack) {
        return new xr(regex,haystack);
    }

    public pattern p;
    public matcher m;

    public xr(string regex, string haystack) {
        p = pattern.compile( regex );
        m = p.matcher(haystack);
    }

    public boolean find() {
        return m.find();
    }

    public string group(integer i) {
        try {
            return m.group(i);
        } catch(exception e) {
            return null;
        }
    }

    public integer end(integer i) {
        try {
            return m.end(i);
        } catch(exception e) {
            return null;
        }
    }

    public integer start(integer i) {
        try {
            return m.start(i);
        } catch(exception e) {
            return null;
        }
    }

    public string pick(integer i) {
        //if(m.find()) return m.group(1); else return '';
        if(m.find()) return m.group(i); else return '';
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.