Working with Features Licenses:

Published on: August 18, 2022
hero
Table of Contents:

Software Vendors often require the ability to control the entitlements for specific components or modules individually within the main application. LicenseSpring achieves this through our features licensing capability. LicenseSpring allows two types of features licensing, consumption, and activation-based features. In this tutorial, we will cover adding these features, when to use both types, and best practices when using feature licenses.

For more information regarding LicenseSpring’s Feature Licensing, see Features Licensing: How to license features within your software application with LicenseSpring.

Sections:

  • Adding Features
  • Locking and Unlocking Application Modules with Features
  • Features Consumption and Incrementing Total Consumptions back to LicenseSpring
  • Best Practices on License Checks for Expiry Dates

Adding Features:

Steps to add Feature to Product

You will then need to define a feature’s name, its code, and whether it’s of type activation or consumption. If it is a consumption-based feature, you will then specify the default number of max consumptions. You can change the default value when issuing licenses. 

You can associate features to a license when you issue them. Since features are dynamic entitlements, you can also add or remove them even after the license has been issued. For consumption-based features, you can change the total available consumptions at any time. This can be done either manually through the platform, or programmatically, by using the management API.

Adding Feature to License

Locking and Unlocking Application with Features:

Features Activation allows the vendor to either include or exclude specific features from a license. You can lock off a module/method by simply using:

cpp
1 LicenseFeature feature = license->feature(“feature code”);

And inputting the feature code. When the activation feature with the same feature code is not added to your license, this line of code will throw an InvalidLicenseFeatureException exception.

You can catch this exception and respond with a message saying that this feature is currently locked, and what the user has to do to unlock this feature. Once a user completes that, you can add the feature onto their license from the LicenseSpring platform, and then the user will no longer get that exception and they can access the module.

Features Consumption and Incrementing Total Consumptions back to LicenseSpring:

Consumption Licensing allows for metered usage of a feature in the app. This can be useful if the vendor would like to limit the number of times a certain function is run, or a certain report is generated, for example. In order to adjust consumption levels of features, we use:

cpp
1 license->updateFeatureConsumption( "feature_code", 1, true );

The first parameter passed is the unique feature code of the feature we are updating, the second parameter is the consumption value to be added, and the final parameter dictates whether it is to be saved locally. 

There are two ways to measure consumption on a device. Local consumption and total consumption.

If you are using local consumption for a particular feature, then consumptions will only be read from the local license file, and not the backend. This could be useful to cache the amount of local consumption per device, since LicenseSpring charges per API call, so you can set it up so that the local consumption only gets synced with the backend when the program ends or some other scenario.

Total consumption is different in that it is equal to the total consumption on the LicenseSpring platform + the local consumption on the device. Thus, if you are using total consumption for a particular feature, all users on the same license will share the same consumption pool that is shown on the platform. When working with total consumption, it is generally recommended to use:

cpp
1 license->syncFeatureConsumption( "feature_code");

Before trying to obtain the total consumption value and after updating the total consumption count. This is so that the LicenseSpring platform, as well as the consumption count on each device, is consistent when reading or writing from/to the total consumption value. 

If you are syncing properly, then your total consumption should be equal to your local consumption at any time.

Best Practices on License Checks for Expiry Dates:

When the expiry date of a feature passes, the feature is completely deleted from the license. Since feature availability is returned by the server on activation or license check, it is important to consistently check the license. This will keep the application up to date, with the proper features available for use. Furthermore, you can also use:

cpp
1 license->syncFeatureConsumption( "feature_code");

To check for expired features, since when the feature is deleted from the license, syncFeatureConsumption won’t be able to find it on the LicenseSpring platform, and will throw an InvalidLicenseFeatureException exception.

Finally, if the application needs to check expiry dates offline, the expiry date for each feature is saved to the local license and can be accessed as so:

cpp
1 2 LicenseFeature feature = license->feature(“feature code”); feature.isExpired();

Common Problems:

When using activation features, make sure to be syncing their license with the backend using online activations and checks or offline activations and updates. If you add an activation feature to a license, expecting the user to be able to access that module, their license will need to be synced up with the backend again, so that feature will be incorporated into their local license.

Note: When first activating your license, your local consumption will be equal to your total consumption, which should match what is displayed on the LicenseSpring platform at the time of activation. Online checks will also sync up your consumption counts with the LicenseSpring platform, although this will not affect your local consumption, this will change your total consumption. So you may end up in a scenario where your total consumption is more than your local consumption. This could cause errors since updateFeatureConsumption will throw an exception when your total consumption is equal to your max consumption. 

Example:

Let’s say you want to create a license where each user has 3 consumptions for a certain feature, and you use local consumption to achieve this. You may run into this error.

  • License is created with feature 1.
  • Feature 1 has 3 max consumptions on the LicenseSpring backend. 
  • User 1 and User 2 both activate their license, starting with 0 total and local consumptions each.
  • User 1 uses the feature 3 times and uses updateFeatureConsumption each time.
  • User 1 now has 3 total and local consumptions.
  • User 1 performs an online check, updating the LicenseSpring platform total activations to be 3.
  • User 2 performs an online check, updating the total consumptions on their local license to 3, but their local consumption remains at 0.
  • User 2 now tries to use the feature and updateFeatureConsumption, thinking they have 3 uses since their local consumption is still at 0.
  • updateFeatureConsumption throws an exception since their total consumption is equal to their max activations.

Note: The opposite may also occur, where you are using local consumption to cache the number of consumptions to minimize the number of API calls, but since local consumptions have no connection to the LicenseSpring server, it could cause overconsumption. 

Example:

Let’s say you have a license with 2 users both sharing a total of 3 consumptions.

  • License is created with feature 1.
  • Feature 1 has 3 max consumptions on the LicenseSpring backend.
  • User 1 and User 2 both activate their license, starting with 0 total and local consumptions each.
  • User 1 and User 2 both use all 3 of their consumptions.
  • User 1 and User 2 sync up their license, either using syncFeatureConsumption, or an online check.
  • In total, both users had 6 consumptions combined, when they were only supposed to use 3.

In a case like this, constantly syncing and checking your license is recommended. If being online is not an option, this issue is very similar to offline consumption which can be found here.

Resetting a license does not reset the total consumption of a consumption-based feature. It only resets the activation of a license. Currently, to reset a feature’s total consumption, you can delete that consumption feature, and add it back in.