11

I'm trying to write a simple method to extract the package version (using System.requestVersion()) and convert it to a string. The documentation for that method indicates that it will throw an exception if called from an unmanaged package. I've since found that it's throwing a System.ProcedureException.

But I can't figure out how to either:

  • Determine if I'm in a managed package before trying to call the method.
  • Catch the exception so I can return null to the caller.

The code below throws a System.ProcedureException: Method is not supported from an unmanaged namespace on the line calling System.requestVersion() but it isn't caught by the catch block for some reason.

public static String packageVersion()
{
    try
    {
        System.Version v = System.requestVersion();
        String versionString = v.major() + '.' + v.minor();
        if (v.patch() != null)
        {
            versionString += '.' + v.patch();
        }
        return versionString;
    }
    catch (Exception e) { /* ignore exceptions and return null */ }

    return null;
}

I've tried both catching all exceptions (shown above) and just catching System.ProcedureExceptions. Both fail to catch.

Looking for help with either of the bullet points at the top of the question -- code to know if it's safe to call, or a way to catch the exception.

10

It looks like System.ProcedureException is yet another uncatchable exception. I think your only option here is to avoid having that exception thrown.

You can detect if you're in an unmanaged context with some careful use of the UserInfo. isCurrentUserLicensed method. A careful read of the docs shows it throws a System.TypeException if the namespace passed is not installed in the current org, so you could make a method that detects an unmanaged context and avoids the call to requestVersion():

public static boolean isManaged(){
    boolean result;
    try{
        UserInfo.isCurrentUserLicensed('your_namespace');
        result = true;
    }catch(System.TypeException e){
        result = false;
    }
    return result;  
}

Since you only care if the package is managed, not if the user is actually licensed, you ignore the return value of isCurrentUserLicensed and only check if it throws a TypeException here.

  • 1
    Thanks, I ended up integrating that into my solution, checking isManaged() before calling System.requestVersion(). – tomlogic Jul 2 '13 at 17:16
  • UserInfo.isCurrentUserLicensed() method will no longer be available from salesforce summer '19 release – Varatharaj May 21 at 14:06
  • @Varatharaj older Apex API versions will continue to be able to use this method. For Apex on the new API version there's a replacement, UserInfo.isCurrentUserLicensedForPackage(packageId). I reached out to check why this wasn't properly documented. The packageId starts with 033 if you're trying to find a specific one. – ca_peterson May 28 at 21:40
  • @ca_peterson you are right, I tried to say that if our APEX class API version is set to 46 then the old method will not be available.Salesforce will throw this error "Method was removed after version 45.0: isCurrentUserLicensed" – Varatharaj Jun 3 at 8:11
-1
    /*
 * Returns true for Managed package
 */
public static Boolean isManaged() {
    //null for unmanaged package
    if (getNameSpacePrefix() == null) {
        return false;
    } else {
        return true;
    }
}
/*
 * Returns namespacePrefix.
 * null for unmanaged package
 * <namespace name> for managed package in PROD
 */
public static String getNameSpacePrefix() {

    Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe(); 
    Set<String> gdKeys = new Set<String>();
    gdKeys = gd.keySet();
    integer indexOfToken = -1;
    // Token Sobject Name, this can be any Custom Sobject name from your product.Replace CustomObjectName with ur custom object name
    String TOKEN_SOBJECT_NAME = '__CustomObjectName__c';
    // This variable will have the namespace prefix
    String namespacePrefix = null;
    for (String sobjName: gdKeys) {
            System.debug('sobjName:'+sobjName);
        if (sobjName != null) {
            // Try matching each Sobject Name with the TOKEN Sobject
                indexOfToken = sobjName.indexOf(TOKEN_SOBJECT_NAME);
            }

        if (indexOfToken != -1) {
            // If match is success, then substring the namespace prefix
            namespacePrefix = sobjName.substring(0, indexOfToken);
            break;
        }

    }
    System.debug('namespacePrefix:'+namespacePrefix);
    return namespacePrefix;

}

Vijay

  • Vijay, your answer doesn't really address my question. You can have a namespace, but not be in a managed package (for example, working in the org used to build the package). – tomlogic Jul 2 '13 at 17:15

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.