Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Warning

This functionality is only available with the Multi Tenancy License. Please contact Blueriq Support.


Setting up a multi-tenant Runtime is actually quite easy. It starts with enabling multi-tenancy in the Runtime itself and configuring which tenants are allowed to access the runtime. Once this is done, for each component that has a datasource (such as the Process Engine) you need to configure the tenant specific datasource.

After the datasources are configured, the Runtime is set up to be accessed via an HTTP Header called "X-TENANT-ID" (to configure a different header name, please refer to Multi-tenancy Properties). We advise to set up an HTTP server (for example NGINX or Apache HTTPD) which can be configured to add this HTTP header depending on, for instance, the url from which the Runtime is called. Due to the diversity of architectures in which the Runtime resides we also provided a way of overriding the way the Runtime detects the tenant. If so, please refer to this section.


Info

We only support multi-tenancy where each tenant uses the same database vendor. You are not able to mix, for example, an Oracle tenant with an Microsoft SQL Server tenant.


In the sections below you will find an example setup for two tenants called Google and Apple.

Table of Contents
maxLevel4


Enabling multi-tenancy


Code Block
languagepowershell
titleapplication.properties
blueriq.multi-tenancy.enabled=true
blueriq.multi-tenancy.allowed-tenants=google,apple

For additional information, please refer to Multi-tenancy Properties

# rest blueriq.connection.RestCall.http.tenantIdEnabled=true blueriq.connection.RestCall.http.tenantHeaderName=Tenant-Id blueriq.connection.RestCall.http.tenants.blueriq.url=http://something blueriq.connection.RestCall.http.tenants.blueriq.username=username blueriq.connection.RestCall.http.tenants.blueriq.password=password # soap blueriq.connection.SoapService.soap.tenantIdEnabled=true blueriq.connection.SoapService.soap.tenantHeaderName=Tenant-Id blueriq.connection.SoapService.soap.tenants.blueriq.url=http://something blueriq.connection.SoapService.soap.tenants.blueriq.username=username blueriq.connection.SoapService.soap.tenants.blueriq.password=password
Excerpt
Configure components

Configuration

The datasources for the components can be configured either in the  application-externaldatasources.properties file or the application-jndidatasources.properties. When configuring external datasources, the externaldatasources profile should be enabled. When configuration JNDI datasources the jndidatasources profile should be enabled.

JDBC datasources

Code Block
languagepowershell
titleapplication-externaldatasources.properties
### Comments SQL Store ###
blueriq.datasource.comments-sql-store.tenants.google.url=jdbc:oracle:thin:@localhost:1521:orcl
blueriq.datasource.comments-sql-store.tenants.google.username=google
blueriq.datasource.comments-sql-store.tenants.google.password=welcome
blueriq.datasource.comments-sql-store.tenants.apple.url=jdbc:oracle:thin:@localhost:1521:orcl
blueriq.datasource.comments-sql-store.tenants.apple.username=apple
blueriq.datasource.comments-sql-store.tenants.apple.password=welcome
blueriq.datasource.comments-sql-store.driverClassName=oracle.jdbc.driver.OracleDriver
blueriq.hibernate.comments-sql-store.hbm2ddl.auto=validate
blueriq.hibernate.comments-sql-store.dialect=org.hibernate.dialect.Oracle12cDialect

### Process SQL Store ###
blueriq.datasource.process-sql-store.tenants.google.url=jdbc:oracle:thin:@localhost:1521:orcl
blueriq.datasource.process-sql-store.tenants.google.username=google
blueriq.datasource.process-sql-store.tenants.google.password=welcome
blueriq.datasource.process-sql-store.tenants.apple.url=jdbc:oracle:thin:@localhost:1521:orcl
blueriq.datasource.process-sql-store.tenants.apple.username=apple
blueriq.datasource.process-sql-store.tenants.apple.password=welcome
blueriq.datasource.process-sql-store.driverClassName=oracle.jdbc.driver.OracleDriver
blueriq.hibernate.process-sql-store.hbm2ddl.auto=validate
blueriq.hibernate.process-sql-store.dialect=org.hibernate.dialect.Oracle12cDialect

### Trace SQL Store ###
blueriq.datasource.trace-sql-store.tenants.google.url=jdbc:oracle:thin:@localhost:1521:orcl
blueriq.datasource.trace-sql-store.tenants.google.username=google
blueriq.datasource.trace-sql-store.tenants.google.password=welcome
blueriq.datasource.trace-sql-store.tenants.apple.url=jdbc:oracle:thin:@localhost:1521:orcl
blueriq.datasource.trace-sql-store.tenants.apple.username=apple
blueriq.datasource.trace-sql-store.tenants.apple.password=welcome
blueriq.datasource.trace-sql-store.driverClassName=oracle.jdbc.driver.OracleDriver
blueriq.hibernate.trace-sql-store.hbm2ddl.auto=validate
blueriq.hibernate.trace-sql-store.dialect=org.hibernate.dialect.Oracle12cDialect

JNDI datasources

Code Block
languagepowershell
titleapplication-jndidatasources.properties
### Comments SQL Store ###
blueriq.datasource.comments-sql-store.tenants.google.jndiName=java:/comp/env/jdbc/google
blueriq.datasource.comments-sql-store.tenants.apple.jndiName=java:/comp/env/jdbc/apple

blueriq.hibernate.comments-sql-store.hbm2ddl.auto=validate
blueriq.hibernate.comments-sql-store.dialect=org.hibernate.dialect.Oracle12cDialect

### Process SQL Store ###
blueriq.datasource.process-sql-store.tenants.google.jndiName=java:/comp/env/jdbc/google
blueriq.datasource.process-sql-store.tenants.apple.jndiName=java:/comp/env/jdbc/apple

blueriq.hibernate.process-sql-store.hbm2ddl.auto=validate
blueriq.hibernate.process-sql-store.dialect=org.hibernate.dialect.Oracle12cDialect

### Trace SQL Store ###
blueriq.datasource.trace-sql-store.tenants.google.jndiName=java:/comp/env/jdbc/google
blueriq.datasource.trace-sql-store.tenants.apple.jndiName=java:/comp/env/jdbc/apple

blueriq.hibernate.trace-sql-store.hbm2ddl.auto=validate
blueriq.hibernate.trace-sql-store.dialect=org.hibernate.dialect.Oracle12cDialect

CMIS 

To configure CMIS in a multi-tenant environment, Blueriq supports setting the following properties per tenant:

  • user
  • password
  • servicesUrl
  • repositoryId

The rest of the CMIS properties are the same for all tenants. See How to setup a CMIS connection for the further configuration.

Note that it is not necessary to override the above properties for each tenant. If they are not defined for a tenant, the normal (not tenant-specific) properties are used.

Below is a sample configuration for two tenants, where the 'google' tenant uses the standard servicesUrl, while the 'apple' tenant overrides this.

Code Block
# common
blueriq.cmis.services-url=http://host:8080/alfresco/api/-default-/public/cmis/versions/1.1/atom
blueriq.cmis.object-type-id=D:my:objectType
blueriq.cmis.binding-type=atompub

# multi-tenant google
blueriq.cmis.tenants.google.user=admin
blueriq.cmis.tenants.google.password=adminpass
blueriq.cmis.tenants.google.repository-id=google

# multi-tenant apple
blueriq.cmis.tenants.apple.services-url=http://apple.local:8080/alfresco/api/-default-/public/cmis/versions/1.1/atom
blueriq.cmis.tenants.apple.user=apple
blueriq.cmis.tenants.apple.password=applepassword
blueriq.cmis.tenants.apple.repository-id=apple

DCM Lists Service


Connections

The file system connection requires a different connection to the file system for each tenant. This way of storing data allows the data of different tenants to be stored on the same file system. For long term storage, a better way to store files is to use a DMS (Document Management System) instead. This can be achieved using the CMIS connection.When multi-tenancy is enabled, the runtime will send the X-TENANT-ID HTTP header to the DCM lists service whenever an HTTP request is made. To use a separate RabbitMQ instance for each tenant, additional configuration is required in application-dcm-lists-client.properties

Code Block
languagetext
titleapplication-dcm-lists-client.properties.properties
blueriq.dcmconnection.lists-clientconnectionName.rabbitmqfilesystem.tenants.google.host=localhost
blueriq.dcm.lists-client.rabbitmq.tenants.google.port=5672path=C:/google/files

blueriq.dcmconnection.lists-clientconnectionName.rabbitmqfilesystem.tenants.googleapple.username=google
blueriq.dcm.lists-client.rabbitmq.tenants.google.password=welcome
blueriq.dcm.lists-client.rabbitmq.tenants.google.exchangeName=processEvents
blueriq.dcm.lists-client.rabbitmq.tenants.google.virtualHost=google
blueriq.dcm.lists-client.rabbitmq.tenants.google.queueNames=dcmListsService

blueriq.dcm.lists-client.rabbitmq.tenants.apple.host=localhost
blueriq.dcm.lists-client.rabbitmq.tenants.apple.port=5672
blueriq.dcm.lists-client.rabbitmq.tenants.apple.username=apple
blueriq.dcm.lists-client.rabbitmq.tenants.apple.password=welcome
blueriq.dcm.lists-client.rabbitmq.tenants.apple.exchangeName=processEvents
blueriq.dcm.lists-client.rabbitmq.tenants.apple.virtualHost=apple
blueriq.dcm.lists-client.rabbitmq.tenants.apple.queueNames=dcmListsService

DCM / Case Engine

path=C:/apple/files

Rest & soap

The rest and soap filesystem connections can also be configured for each tenant. Most properties will be the same for each tenant, except for url, username and password. These can be configured for each tenant. In a multi-tenancy setup, two additional (optional) properties are added for soap and rest connections. It is possible to pass the tenant with your rest call, for example when you want to call a BAARS or an external application that is multi-tenant as well. To do this the tenant header should be enabled with the property tenantIdEnabled and the header can be set in the property tenantHeaderName. An example setup will look as follows:

Code Block
languagetext
titleapplication.properties
# rest
blueriq.connection.RestCall.http.tenantIdEnabled=true
blueriq.connection.RestCall.http.tenantHeaderName=Tenant-Id
blueriq.connection.RestCall.http.tenants.blueriq.url=http://something
blueriq.connection.RestCall.http.tenants.blueriq.username=username
blueriq.connection.RestCall.http.tenants.blueriq.password=password

# soap
blueriq.connection.SoapService.soap.tenantIdEnabled=true
blueriq.connection.SoapService.soap.tenantHeaderName=Tenant-Id
blueriq.connection.SoapService.soap.tenants.blueriq.url=http://something
blueriq.connection.SoapService.soap.tenants.blueriq.username=username
blueriq.connection.SoapService.soap.tenants.blueriq.password=password

DCM Lists Client

When multi-tenancy is enabled, the runtime will send the X-TENANT-ID HTTP header to the DCM lists service whenever an HTTP request is made. To use a separate RabbitMQ instance for each tenant, additional configuration is required in application-dcm-lists-client.propertiesThe DCM module provides the Service call type: DCM_CaseCreate service call type that you can use to start a case by publishing data on a queue. The Case Engine will consume messages from the queue and start the case asynchronously. Below are examples on how to configure the RabbitMQ instance for each tenant.

Code Block
languagetext
titleapplication-dcm-lists-client.properties
collapsetrue
blueriq.dcm.lists-client.rabbitmq.tenants.google.host=localhost
blueriq.dcm.lists-client.rabbitmq.tenants.google.port=5672
blueriq.dcm.lists-client.rabbitmq.tenants.google.username=google
blueriq.dcm.lists-client.rabbitmq.tenants.google.password=welcome
blueriq.dcm.lists-client.rabbitmq.tenants.google.exchangeName=processEvents
blueriq.dcm.lists-client.rabbitmq.tenants.google.virtualHost=google
blueriq.dcm.lists-client.rabbitmq.tenants.google.queueNames=dcmListsService

blueriq.dcm.lists-client.rabbitmq.tenants.apple.host=localhost
blueriq.dcm.lists-client.rabbitmq.tenants.apple.port=5672
blueriq.dcm.lists-client.rabbitmq.tenants.apple.username=apple
blueriq.dcm.lists-client.rabbitmq.tenants.apple.password=welcome
blueriq.dcm.lists-client.rabbitmq.tenants.apple.exchangeName=processEvents
blueriq.dcm.lists-client.rabbitmq.tenants.apple.virtualHost=apple
Code Block
languagetext
titleapplication-case-engine.properties
blueriq.casedcm.enginelists-client.rabbitmq.tenants.googleapple.queueNames=dcmListsService

DCM / Case Engine

The DCM module provides the Service call type: DCM_CaseCreate service call type that you can use to start a case by publishing data on a queue. The Case Engine will consume messages from the queue and start the case asynchronously. Below are examples on how to configure the RabbitMQ instance for each tenant.

Code Block
languagetext
titleapplication.properties
collapsetrue
blueriq.dcm.rabbitmq.tenants.google.host=localhost
blueriq.dcmhost=localhost
blueriq.case.engine.rabbitmq.tenants.google.port=5672
blueriq.case.engine.rabbitmq.tenants.google.username=google
blueriq.case.engine.rabbitmq.tenants.google.passwordport=welcome5672
blueriq.case.enginedcm.rabbitmq.tenants.google.virtualHostusername=google
blueriq.case.enginedcm.rabbitmq.tenants.google.queueNamespassword=dcmListsService
welcome
blueriq.case.enginedcm.rabbitmq.tenants.applegoogle.hostexchangeName=localhostprocessEvents
blueriq.case.enginedcm.rabbitmq.tenants.applegoogle.portvirtualHost=5672google

blueriq.case.enginedcm.rabbitmq.tenants.apple.host=localhost
blueriq.dcm.rabbitmq.tenants.apple.port=5672
blueriq.dcm.rabbitmq.tenants.apple.username=apple
blueriq.case.enginedcm.rabbitmq.tenants.apple.password=welcome
blueriq.case.enginedcm.rabbitmq.tenants.apple.virtualHostexchangeName=appleprocessEvents
blueriq.case.enginedcm.rabbitmq.tenants.apple.queueNames=dcmListsService

Default RabbitMQ multi-tenant properties

Because it can be tedious to configure all components of the Runtime with the same properties, a Default properties mechanism was added with Blueriq 16.7.

The following example shows default rabbitmq properties in a multi-tenant setup. There you can see how you can configure rabbitmq properties per tenant which will then be used for each component that uses rabbitmq instead of specifying it per component.

Because queue and exchange names are specific per component you still need to configure them as stated above.

This configuration will be used for each component that has no specific properties configured (except the queue and/or exchange names). 

When neither specific nor default properties are configured for a tenant, the runtime will try to use the default rabbitmq properties for this tenant.

virtualHost=apple
Code Block
languagetext
titleapplication-case-engine.properties
collapsetrue
# DCM Events
blueriq.dcm.rabbitmq.tenants.google.host=localhost
blueriq.dcm.rabbitmq.tenants.google.port=5672
blueriq.dcm.rabbitmq.tenants.google.username=google
blueriq.dcm.rabbitmq.tenants.google.password=welcome
blueriq.dcm
Code Block
languagetext
titleapplication-case-engine.properties
blueriq.default.rabbitmq.tenants.google.host=localhost
blueriq.default.rabbitmq.tenants.google.portexchangeName=5672processEvents
blueriq.defaultdcm.rabbitmq.tenants.google.usernamevirtualHost=google

blueriq.defaultdcm.rabbitmq.tenants.googleapple.passwordhost=welcomelocalhost
blueriq.defaultdcm.rabbitmq.tenants.googleapple.virtualHostport=google5672
blueriq.defaultdcm.rabbitmq.tenants.googleapple.ssl.enabled=true
username=apple
blueriq.defaultdcm.rabbitmq.tenants.apple.hostpassword=localhostwelcome
blueriq.defaultdcm.rabbitmq.tenants.apple.portexchangeName=5672processEvents
blueriq.defaultdcm.rabbitmq.tenants.apple.usernamevirtualHost=apple

#Trace Event Publisher
blueriq.default.trace.event.publisher.channel.amqp.rabbitmq.tenants.applegoogle.passwordhost=welcomelocalhost
blueriq.defaulttrace.event.publisher.channel.amqp.rabbitmq.tenants.applegoogle.virtualHostport=DefaultEverest5672
blueriq.defaulttrace.event.publisher.channel.amqp.rabbitmq.tenants.applegoogle.ssl.enabled=true

Parameters can be configured at three levels for RabbitMQ or SQL-Datasources and MongoDB:

  • default properties
    blueriq.default.rabbitmq.*
    blueriq.default.datasource.*
    blueriq.default.mongodb.*
  • default tenant-specific properties for all sources for that tenant:
    blueriq.default
    username=google
    blueriq.trace.event.publisher.channel.amqp.rabbitmq.tenants.google.password=welcome
    blueriq.trace.event.publisher.channel.amqp.rabbitmq.tenants.
    <tenant_name>.*
    google.virtualHost=google
    blueriq.
    default
    trace.
    datasource
    event.
    tenants
    publisher.
    <tenant_name>.*
    blueriq.default.mongodb
    channel.amqp.rabbitmq.tenants.
    <tenant_name>.*tenant and component specific properties
    blueriq.<component>.<path>
    google.exchangeName=traceEvents
    
    blueriq.trace.event.publisher.channel.amqp.rabbitmq.tenants.
    <tenant_name>.*
    blueriq.datasource.<component>.tenants.<tenant_name>.*
    blueriq.<component>.mongodb.tenants.<tenant_name>.*

    The properties supersede each other from general to more specific. So any properties from the most general level (default properties) will be overwritten by the other more specific levels. Example configuration:

    Code Block
    languagetext
    titleapplication-case-engine.properties
    # Generic level, all sources share the same host and port
    blueriq.default.rabbitmq.host=localhost
    blueriq.default.rabbitmq.port=5672
    blueriq.default.rabbitmq.ssl.enabled=true
    
    # a different user and virtual host is used for each tenant (for all queue connections at this tenant) 
    blueriq.defaultapple.host=localhost
    blueriq.trace.event.publisher.channel.amqp.rabbitmq.tenants.apple.port=5672
    blueriq.trace.event.publisher.channel.amqp.rabbitmq.tenants.apple.username=apple
    blueriq.trace.event.publisher.channel.amqp.rabbitmq.tenants.apple.password=welcome
    blueriq.trace.event.publisher.channel.amqp.rabbitmq.tenants.apple.virtualHost=apple
    blueriq.trace.event.publisher.channel.amqp.rabbitmq.tenants.apple.exchangeName=traceEvents
    
    # Trace Event Listener
    blueriq.trace.event.listener.amqp.rabbitmq.tenants.google.usernamehost=googlelocalhost
    blueriq.default.trace.event.listener.amqp.rabbitmq.tenants.google.passwordport=welcome5672
    blueriq.defaulttrace.event.listener.amqp.rabbitmq.tenants.google.virtualHostusername=google
    
    blueriq.default.trace.event.listener.amqp.rabbitmq.tenants.applegoogle.usernamepassword=applewelcome
    blueriq.default.trace.event.listener.amqp.rabbitmq.tenants.applegoogle.passwordvirtualHost=welcomegoogle
    blueriq.defaulttrace.event.listener.amqp.rabbitmq.tenants.applegoogle.virtualHostqueueNames=apple
    
    # different components use different queues, which is most the specific leveltraceQueue
    
    blueriq.trace.event.publisher.channellistener.amqp.rabbitmq.tenants.googleapple.exchangeNamehost=traceEventslocalhost
    blueriq.trace.event.publisher.channellistener.amqp.rabbitmq.tenants.apple.exchangeNameport=traceEvents
    
    # for one specific connection, all settings are overwritten
    blueriq.audit5672
    blueriq.trace.event.listener.amqp.rabbitmq.tenants.googleapple.hostusername=host_xapple
    blueriq.audit.trace.event.listener.amqp.rabbitmq.tenants.googleapple.portpassword=8080welcome
    blueriq.audit.trace.event.listener.amqp.rabbitmq.tenants.googleapple.usernamevirtualHost=googleapple
    blueriq.audit.trace.event.listener.amqp.rabbitmq.tenants.googleapple.password=welcomequeueNames=traceQueue
    
    # Timeline Event Publisher
    blueriq.audit.timeline.event.publisher.channel.amqp.rabbitmq.tenants.google.virtualHosthost=googlelocalhost
    blueriq.audit.timeline.event.publisher.channel.amqp.rabbitmq.tenants.google.exchangeNameport=auditEvents
    5672
    blueriq.audit.timeline.event.publisher.channel.amqp.rabbitmq.tenants.google.hostusername=host_xgoogle
    blueriq.audittimeline.rabbitmqevent.tenantspublisher.google.port=8080
    blueriq.auditchannel.amqp.rabbitmq.tenants.google.usernamepassword=googlewelcome
    blueriq.audittimeline.rabbitmqevent.tenantspublisher.google.password=welcome
    blueriq.auditchannel.amqp.rabbitmq.tenants.google.virtualHost=google
    blueriq.audit.timeline.event.publisher.channel.amqp.rabbitmq.tenants.google.virtualHostexchangeName=googletimelineEvents
    
    blueriq.audit.timeline.event.publisher.channel.amqp.rabbitmq.tenants.googleapple.exchangeName=auditEvents

    Connections

    The file system connection requires a different connection to the file system for each tenant. This way of storing data allows the data of different tenants to be stored on the same file system. For long term storage, a better way to store files is to use a DMS (Document Management System) instead. This can be achieved using the CMIS connection.

    Code Block
    languagetext
    titleapplication.properties
    blueriq.connection.connectionName.filesystem.tenants.google.path=C:/google/files
    
    blueriq.connection.connectionName.filesystem.tenants.apple.path=C:/apple/files

    Rest & soap

    The rest and soap filesystem connections can also be configured for each tenant. Most properties will be the same for each tenant, except for url, username and password. These can be configured for each tenant. In a multi-tenancy setup, two additional (optional) properties are added for soap and rest connections. It is possible to pass the tenant with your rest call, for example when you want to call a BAARS or an external application that is multi-tenant as well. To do this the tenant header should be enabled with the property tenantIdEnabled and the header can be set in the property tenantHeaderName. An example setup will look as follows:

    Code Block
    languagetext
    titleapplication.properties
    host=localhost
    blueriq.timeline.event.publisher.channel.amqp.rabbitmq.tenants.apple.port=5672
    blueriq.timeline.event.publisher.channel.amqp.rabbitmq.tenants.apple.username=apple
    blueriq.timeline.event.publisher.channel.amqp.rabbitmq.tenants.apple.password=welcome
    blueriq.timeline.event.publisher.channel.amqp.rabbitmq.tenants.apple.virtualHost=apple
    blueriq.timeline.event.publisher.channel.amqp.rabbitmq.tenants.apple.exchangeName=timelineEvents
    
    # Timeline Event Listener
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.google.host=localhost
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.google.port=5672
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.google.username=google
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.google.password=welcome
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.google.virtualHost=google
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.google.queueNames=timelineQueue
    
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.apple.host=localhost
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.apple.port=5672
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.apple.username=apple
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.apple.password=welcome
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.apple.virtualHost=apple
    blueriq.timeline.event.listener.amqp.rabbitmq.tenants.apple.queueNames=timelineQueue
    
    # Audit Event Publisher
    blueriq.audit.rabbitmq.tenants.google.host=localhost
    blueriq.audit.rabbitmq.tenants.google.port=5672
    blueriq.audit.rabbitmq.tenants.google.username=google
    blueriq.audit.rabbitmq.tenants.google.password=welcome
    blueriq.audit.rabbitmq.tenants.google.virtualHost=google
    blueriq.audit.rabbitmq.tenants.google.exchangeName=auditEvents
    
    blueriq.audit.rabbitmq.tenants.apple.host=localhost
    blueriq.audit.rabbitmq.tenants.apple.port=5672
    blueriq.audit.rabbitmq.tenants.apple.username=apple
    blueriq.audit.rabbitmq.tenants.apple.password=welcome
    blueriq.audit.rabbitmq.tenants.apple.virtualHost=apple
    blueriq.audit.rabbitmq.tenants.apple.exchangeName=auditEvents

    Include Page
    _defaultMultiTenantProperties
    _defaultMultiTenantProperties