How to rename or change signature for a namespace accessible or global method?

Let’s assume that we have a base package and package extension.

Let’s assume that we have some base class BasePackageClass in the base package

@namespaceAccessible
public inherited sharing BasePackageClass{
@namespaceAccessible public void method() {}
}

which we extend inside a class ExtensionPackageClass which is part of Extension package

public inherited sharing ExtensionPackageClass extends BasePackageClass{
public override void method() {}
}

Let’s assume we have successfully released package version 1.0 of base package and package version 1.0 of extension package. Now we want to modify either method name or method signature for the BasePackageClass as follows

@namespaceAccessible
public inherited sharing BasePackageClass{
@namespaceAccessible public void method(String a, String b, String c, String d, String e) {}
}

and we also have to modify extensing class ExtensionPackageClass to

public inherited sharing ExtensionPackageClass extends BasePackageClass{
public override void method(String a, String b, String c, String d, String e) {}
}

If we try to build both packages and install them in a fresh org, no error will happen, but if we try to install first package version 1.0 of base and extension packages and then upgrade to base package version 1.1, we will receive an error

Dependent class is invalid and needs recompilation: Class Namespace.ExtensionPackageClass : Method does not exist or incorrect signature: void method(NULL, NULL, NULL, NULL, NULL) from the type Namespace.BasePackageClass

It is clear something wrong here, which means we shouldn’t rename global or namespace accessible method like that, so how should we rename or update signature for a namespace accessible method correctly?

We would have to keep the original signature and name of base class method at least for one release but we can mark it as deprecated like follows

@namespaceAccessible
public inherited sharing BasePackageClass{
@deprecated @namespaceAccessible public void method() {}
@namespaceAccessible public void method(String a, String b, String c, String d, String e) {}
}

while in ExtensionPackageClass we don’t have to keep the original implementation but rather get rid of it

public inherited sharing ExtensionPackageClass extends BasePackageClass{
public override void method(String a, String b, String c, String d, String e) {}
}

Now, why do we have to do this? If we try to upgrade Base Package to 1.1, it fails since classes compilation run during upgrade for both base and extension packages and Extension Package 1.1 cannot be compiled with the code base of Base Package 1.0 since method method has changed signature.

enter image description here

The correct way is to deprecate the base method with old name or old signature and add a TODO comment to delete that method in a subsequent release and update signature of the overridden method method in Extension package 1.1 so that the method without parameters in base class could be deleted in the subsequent release after the current release.

enter image description here

If someone would directly try to upgrade 1.0 to 1.2, that would fail with the same error as we have now, but for that we will have a resolution: someone should upgrade first to 1.1 and Extension Package 1.1 and only after that upgrade to 1.2.

Another option to have dynamic implementation is to use Callable interface.

This entry was posted in apex, extension, namespace, package and tagged , , , . Bookmark the permalink.

Leave a comment