13

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.

3 Answers 3

11

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.

5
  • 1
    Thanks, I ended up integrating that into my solution, checking isManaged() before calling System.requestVersion().
    – tomlogic
    Jul 2, 2013 at 17:16
  • UserInfo.isCurrentUserLicensed() method will no longer be available from salesforce summer '19 release
    – Varatharaj
    May 21, 2019 at 14:06
  • 1
    @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. May 28, 2019 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, 2019 at 8:11
  • @ca_peterson could you clarify what an "unmanaged context" is? I found out that if I run requestVersion() in the dev organization where I develop my 1GP managed package, it returns the current version, but if I run that in a scratch org with the same namespace, it throws the exception mentioned. Sep 7, 2021 at 22:50
-1

isCurrentUserLicensed() is working and not deprecated. Check the salesforce developer documentation. https://developer.salesforce.com/docs/atlas.en-us.212.0.apexcode.meta/apexcode/apex_methods_system_userinfo.htm

1
  • 2
    Welcome to Salesforce Stack Exchange (SFSE)! Thanks for your contribution. For others: the above link goes directly to Apex API v42.0 (Spring '18). If you click onthe "v42.0" at top of the left column (under "Apex Developer Guide" and near the word "Pages") and you select any API version beginning from v46.0 until v54.0 (current as of this writing) you can see both isCurrentUserLicensed(namespace) & isCurrentUserLicensedForPackage(), and the former is not marked as deprecated.
    – Moonpie
    Feb 7 at 20:56
-3
    /*
 * 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

1
  • 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, 2013 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.