Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions guides/multitenancy/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ You should now see the route mapped to your application.

<div class="impl java">

[Learn best practices for schema updates in the Java Guide](../../java/multitenancy#database-update){.learn-more style="margin-top: 20px"}
[Learn best practices for schema updates in the Java Guide](/java/multitenancy#database-update){.learn-more style="margin-top: 20px"}

</div>

Expand Down Expand Up @@ -990,11 +990,20 @@ cds watch --profile dev

:::

## SaaS Registry Dependencies {#saas-dependencies}
## SaaS Dependencies {#saas-dependencies}
Some of the xsuaa-based services your application consumes need to be registered as _reuse services_ to work in multitenant environments. This holds true for the usage of both the SaaS Registry service and the Subscription Manager Service (SMS).

Some of the services your application consumes need to be registered as _reuse services_ to work in multitenant environments. `@sap/cds-mtxs` offers an easy way to integrate these dependencies. It supports some services out of the box and also provides a simple API for plugins.
CAP Java as well as `@sap/cds-mtxs`, each offer an easy way to integrate these dependencies. They support some services out of the box and also provide a simple API for applications. Most notably, you need such dependencies for the following SAP BTP services: [Audit Log](https://discovery-center.cloud.sap/serviceCatalog/audit-log-service), [Event Mesh](https://discovery-center.cloud.sap/serviceCatalog/event-mesh), [Destination](https://discovery-center.cloud.sap/serviceCatalog/destination), [HTML5 Application Repository](https://discovery-center.cloud.sap/serviceCatalog/html5-application-repository-service), and [Cloud Portal](https://discovery-center.cloud.sap/serviceCatalog/cloud-portal-service).

Most notably, you will need such dependencies for the SAP BTP [Audit Log](https://discovery-center.cloud.sap/serviceCatalog/audit-log-service), [Connectivity](https://discovery-center.cloud.sap/serviceCatalog/connectivity-service), [Destination](https://discovery-center.cloud.sap/serviceCatalog/destination), [HTML5 Application Repository](https://discovery-center.cloud.sap/serviceCatalog/html5-application-repository-service), and [Cloud Portal](https://discovery-center.cloud.sap/serviceCatalog/cloud-portal-service) services. All these services are supported natively and can be activated individually by providing configuration in `cds.requires`. In the most common case, you simply activate service dependencies like so:
For CAP Java, all these services are supported natively and SaaS dependencies are automatically created if such a service instance is bound to the CAP Java application, that is, the `srv` module.

:::tip Explicitly activate the Destination service
SaaS dependency for Destination service needs to be activated explicitly in the `application.yaml` due to security reasons. SaaS dependencies for some of the other services can be **de**activated by setting the corresponding property to `false` in the `application.yaml`.

Refer to the `cds.multiTenancy.dependencies` section in the [CDS properties](/java/developing-applications/properties#cds-properties).
:::

For CAP Node.js, all these services are supported natively and can be activated individually by providing configuration in `cds.requires`. In the most common case, you simply activate service dependencies like so:

::: code-group

Expand All @@ -1014,7 +1023,7 @@ Most notably, you will need such dependencies for the SAP BTP [Audit Log](https:

::: details Defaults provided by `@sap/cds-mtxs`...

The Boolean values above activate the default configuration in `@sap/cds-mtxs`:
The Boolean values in the _mtx/sidecar/package.json_ activate the default configuration in `@sap/cds-mtxs`:

```json
"cds": {
Expand All @@ -1038,9 +1047,12 @@ The Boolean values above activate the default configuration in `@sap/cds-mtxs`:

:::

::: details If you need additional services...
### Additional Services

You can use the `subscriptionDependency` setting to provide a similar dependency configuration in your application or CAP plugin _package.json_:
If your CAP Java application uses a service that isn't supported out of the box, you can add a custom dependency by providing a custom handler. Refer to [Define Dependent Services](../../java/multitenancy#define-dependent-services) for details.


In Node.js, you can use the `subscriptionDependency` setting to provide a dependency configuration similar to the standard configuration shown before. Use your application's or CAP plugin's _package.json_:

```json [package.json]
"cds": {
Expand All @@ -1052,11 +1064,12 @@ You can use the `subscriptionDependency` setting to provide a similar dependency
}
```

> The `subscriptionDependency` specifies the property name of the credentials value with the desired `xsappname`, starting from `cds.requires['my-service'].credentials`. Usually it's just `"xsappname"`, but JavaScript objects interpreted as a key path are also allowed, such as `{ "uaa": "xsappname" }` in the example for `audit-log` above.
> The `subscriptionDependency` specifies the property name of the credentials value with the desired `xsappname`, starting from `cds.requires['my-service'].credentials`. Usually it's just `"xsappname"`, but JavaScript objects interpreted as a key path are also allowed, such as `{ "uaa": "xsappname" }` in the defaults example for `portal`.

Alternatively, overriding the [`dependencies`](./mtxs#get-dependencies) handler gives you full flexibility for any custom implementation.

:::

<div id="subscriptiondashboard" />

## Add Custom Handlers

Expand Down
42 changes: 32 additions & 10 deletions java/multitenancy.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,22 +133,44 @@ public void beforeUnsubscribe(UnsubscribeEventContext context) {
The event `DEPENDENCIES` fires when the platform service calls the [`getDependencies` callback](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/ff540477f5404e3da2a8ce23dcee602a.html).
Hence, if your application consumes any reuse services provided by SAP, you must implement the `DEPENDENCIES` event to return the service dependencies of the application.
The event must return a list of all of the dependent services' `xsappname` values.
CAP automatically adds dependencies of services to the list, for which it provides dedicated integrations. This includes AuditLog and Event Mesh.

CAP automatically adds dependencies of services to the list, for which it provides dedicated integrations.

[Learn more about automatically added SaaS dependencies.](/guides/multitenancy/?impl-variant=java#saas-dependencies){.learn-more}

::: tip
The `xsappname` of an SAP reuse service that is bound to your application can be found as part of the `VCAP_SERVICES` JSON structure under the path `VCAP_SERVICES.<service>.credentials.xsappname`.
The `xsappname` of an SAP reuse service that is bound to your application is part of the service binding. The structure of the service binding, and hence the exact location of the `xsappname` field, may vary between services.
:::

The following example shows this in more detail:

```java
@Value("${vcap.services.<my-service-instance>.credentials.xsappname}")
private String xsappname;

@On
public void onDependencies(DependenciesEventContext context) {
List<Map<String, Object>> dependencies = new ArrayList<>();
dependencies.add(SaasRegistryDependency.create(xsappname));
context.setResult(dependencies);
@Component
@Profile("cloud")
@ServiceName(DeploymentService.DEFAULT_NAME)
public class SubscriptionHandler implements EventHandler {
private static final String SERVICE_NAME = "my-service";

@Autowired
private CdsRuntime cdsRuntime;

@On
public void onDependencies(DependenciesEventContext context) {
List<Map<String, Object>> dependencies = new ArrayList<>();
Optional<ServiceBinding> service = cdsRuntime.getEnvironment().
getServiceBindings().filter(binding -> binding.getServiceName().
get().equals(SERVICE_NAME)).findFirst();

if (service.isPresent()) {
String xsappname = extractXsappname(service.get().getCredentials());
dependencies.add(SaasRegistryDependency.create(xsappname));
}
context.setResult(dependencies);
}

private String extractXsappname(Map<String, Object> credentials) {
// location of the `xsappname` in the credentials is service specific
}
}
```

Expand Down