Skip to Content
Technical Articles
Author's profile photo Brian McDonnell

Understanding Dependencies in SaaS Provisioning

If you operate a multitenant application in SAP BTP’s Cloud Foundry environment, you’re probably familiar with the Saas Provisioning service. This service allows you, the application operator, to control customer subscriptions by specifying endpoints that SAP BTP will call during subscription events. Tasks like setting up database artifacts, mapping routes and initializing default configuration can be defined in these callbacks allowing for automation of certain aspects of customer onboarding. In fact, the CAP Framework has standardized part of this onboarding processes including the provisioning of HDI containers.

But beyond subscription management, there is a third aspect to the SaaS Provisioning service responsible for allowing subscribers to access services instantiated in your provider account. This is the governed by the getDependencies callback and is the focus of this post.

Get Dependencies

When do you need to use getDependencies? The official documentation gives us a hint:

If your application consumes any reuse services provided by SAP, you must implement the getDependencies callback to return the service dependencies of the application. The callback must return a 200 response code and a JSON file with the dependent services appName and appId, or just the xsappname.

[emphasis mine]

The key term from that snippet is reuse services. If you use a reuse service and want your subscribers to have access, getDependencies must return it. But how do you know if a service is a reuse service, is there a list somewhere? As far as I know, the answer is no. Still, experience has shown these services fit the description:

  1. UI Theme Designer
  2. Job Scheduling Service
  3. Cloud Portal Service
  4. Connectivity/Destinations
  5. UI5 Flexibility for Key Users

[Note: this is not an exhaustive list]

What these services have in common is that they have a certain amount of customer specificity. Each customer could have their own defined themes or scheduled jobs or destinations. Absent a complete list or even an indicator in the service documentation itself, this is the primary signal we have to include a service in the callback response.

Dependency Relevant Events

Now that we have an understanding of when we need to define getDependencies and what services we need to included in its response, the next step is to understand when SAP BTP will attempt to getDependencies. As you might expect, it accesses this endpoint during subscription creation and update events.

Creating a Subscription

The create event is an obvious place to retrieve a list of dependencies that need to be accessible by a new customer. Indeed, in addition to the onSubscription endpoint, the getDependencies endpoint is also accessed. So when activating the new subscription from the customer subaccount, SAP BTP calls both onSubscription and getDependencies to complete the subscription.

Update Subscription

The update event is naturally the next place that needs access to a list of dependencies. In the operation of any application, there’s a good chance you’ll want to add new services to enhance existing functionality. In these cases, you need a mechanism to re-trigger the getDependencies call so SAP BTP can retrieve an updated list of services needed by the subscribed customer.

While the initial subscription has an obvious mechanism to trigger the create event (creating a subscription within the subaccount cockpit), there is no corresponding obvious mechanism to trigger an update. It’s at this point that we need to consult the SaaS Provisioning API.

In the section labeled Application Opeartions for App Providers, we find this endpoint:

PATCH /saas-manager/v1/application/tenants/{tenantId}/subscriptions

With the description:

Update the dependencies of a multitenant application.

This is precisely what we’re looking for. To refresh the dependencies, all we need to do is update the response to the getDependencies endpoint to include the new service and then execute that PATCH request against the tenant to update.

But there is a wrinkle to this endpoint that is not documented. While it does indeed trigger a new call to getDependencies it also triggers a new call to onSubcription. This can be problematic if you assumed onSubscription will only be accessed during the subscription creation.

Luckily, there is a field included in the onSubscription request body that allows us to distinguish which event this is, the eventType field. For new subscriptions, the value is CREATE while in subscription updates the value is UPDATE. So, if you have logic in onSubscription you only wanted executed on subscription creation, just check the eventType.

Summary

The main takeaway here is that there are two places getDependencies is relevant: during subscription creations and updates. Both events result in calls to both onSubscription and getDependencies so it is important that your onSubscription logic can account for this.

Create

Triggered by creating a subscription in the customer subaccount. Results in these callbacks:

PUT {onSubscription}/{tenantId}
{
  ...
  "eventType": "CREATE"
}

GET {getDependencies}?tenantId={tenantId}

Update

Triggered by accessing the PATCH endpoint in the SaaS Provisioning API. Results in these callbacks:

PUT {onSubscription}/{tenantId}
{
  ...
  "eventType": "UPDATE"
}

GET {getDependencies}?tenantId={tenantId}

Closing Thoughts

Part of my motivation for this post was my inability to find a centralized source of documentation on the specifics of how getDependencies works within the Saas Provisioning service. Maybe this documentation exists and I’m just not good enough to find it and if that’s the case, I invite any readers to share where I can find that. If it does not actually exists, I hope this post can help others that have struggled with the same issues I have.

Thanks!

Assigned Tags

      6 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Matthew Reddy
      Matthew Reddy

      Great information, Brian! I had a tough time with this when I first started with multitenancy and this lays it out very clearly.

      Thanks!

      Author's profile photo Sergei Haller
      Sergei Haller

      Very well written!

      Author's profile photo Stefania Santimbrean
      Stefania Santimbrean

      This is extremely valuable information! I was trying to find if Portal, UI Theme Designer and UI5 Flexibility for Key Users are multitenancy reuse services and here is the only place that actually tells this.

      Many, many thanks for the blog post and shared knowledge!

      Author's profile photo Shaun Oosthuizen
      Shaun Oosthuizen

      Thanks Brian. This is very informative. I had to update dependencies related to the Document Management service and this guided me through the process.

      Author's profile photo Gregor Wolf
      Gregor Wolf

      Hi Brian,

      thank you for this post. It's a pitty that SAP isn't able to provide this information in the first place. I would suggest that you also add the destination service to the list. Maybe you find way how I've implemented the content for the destinations call interresting: Documentation: Deploy SaaS Solutions (MTX) - Dependencies to Destination / Connectivity Service.

      CU
      Gregor

      Author's profile photo Brian McDonnell
      Brian McDonnell
      Blog Post Author

      Gregor,

      Thank you for your comments and suggestion.

      I originally considered destinations to be under the umbrella of connectivity functionality given that is how it is presented in the standard docs but I've edited the post to make that fact more clear.

      As for your implementation with MTX, that certainly looks like a clean way to handle this. We originally developed our logic for SaaS in early 2019(!) though so our logic to handle the dependencies callback is a little hackier as MTX didn't exist back then 😅.

      Thanks again!

      Brian