A practical guide for second generation Salesforce managed packages with namespaces

Peter TEMPFLI
5 min readAug 30, 2020

This post will describe how to create two dependent second-generation managed packages and how to share Apex code between them. The post assumes that you know SFDX and have some understanding about packaging.

Sharing Apex code is nothing new — you could do it before by making classes global; however this has a side effect that everybody have access to these classes. Now you can share classes between packages without doing so.

Scaffolding — your orgs

You will need the following orgs:

  • Namespace org
  • Dev Hub
  • Dev org for your package no1
  • Dev org for your package no2

Namespace org

This will be a simple dev org and you don’t need to do anything here, just create a namespace. I call my namspace core2test Once you are done, log out and keep the credentials.

Dev Hub

Second generation package uploads works differently from first generation packages. Instead of having your metadata in a package org, you just send your metadata every time when you want to create a new release. The advantage is obvious: instead of having your metadata both in your packaging org and in your repo, now you have it only in your repo.

Your Dev Hub works as a package registry. It doesn’t own your namespace. It means that you can have more than one namespace linked to your Dev Hub.

So now I need to link core2test namespace to the dev hub. Follow these steps.

The first package

Now you can create your app. You can develop in any org, dev or scratch, doesn’t matter. In fact, you don’t even need an org if you are sure you write good apex and don’t do any mistakes ;) Look at the following class:

This is a normal public class with public methods; however the @namespaceAccessible annotation will make it callable from packages in the same namespace.

Create the package

The following SFDX command creates a package — it means from this point your Dev Hub owns the package and it has a name.

sfdx force:package:create — name core2test — packagetype Managed — path force-app

What is really important: you need to add a property called ‘namespace’ to your sfdx-project.json file.

I assume that you already connected your SFDX to your dev hub! If not — do so!

Uploading a new version

At this point you only registered a package name, but without any releases. In order to create a new release (this is called ‘upload’ in the old terminology), run the following command:

sfdx force:package:version:create — package core2test

It will take a while, but finally you will get your package version. You can list anytime your packages in the dev hub running the following command:

sfdx force:package:version:list

The sfdx-project.json file

It worth to mention that SFDX make some changes in your project definition file. It will have a similar format:

Creating a dependent package

Ok, so your first managed 2nd generation package is created. Now you want to create another package, and access the classes which are shared in the same namespace. This is simple, works like this:

Note that class Core exists in another package, and it is NOT global. You can access it using the core2test namespace because it has the @namespaceAccessible annotation. You DO NOT have the Core metadata in your org; but you have the core2test package installed.

Link the dependent package with dependencies

You need to tell the dependent class (HelloWorld) where to look for the class2test namespace. You need to set up a namespace in your dev org, which you can do by setting the ‘namespace’ property in the project-scratch-def.json file (or whichever definition file you use to create orgs). You need to do so BEFORE creating your org!

Once your org is created, you need to install the package manually (or using the force:package:install command)

Create a dependent package

You create a dependent package the very same way as you created the previous package; using the force:package:create and force:package:version:create commands. Those version will also live in the dev hub, so your dev hub now will contain 2 packages:

When creating the dependent package, you need to set up the dependency in the sfdx-project.json file, by adding a dependencies property to the package definition. It is simple:

And now you can upload a new version!

Summary

I hope I saved you some time with creating your first dependent managed packages. The key points are:

  • Create a namespace and link it to the dev hub
  • Set the namespace property both in sfdx-project.json and in your org definition files.
  • Classes and properties with @namespaceAccessible from the dependency package are available for the dependent package code
  • Create and upload versions of you package to the dev hub
  • You have all your package version in one org (in the dev hub) — but not the metadata itself!
  • You don’t have the metadata uploaded in an org (as a packaging org). The source of truth managed by you (probably in a repo)

--

--