Multitenancy is achieved using Windows Workflow Foundation 4.0 and Windows Communication Foundation 4.0. The Proof of concept (POC) here would meet all the below mentioned requirements. Varied Workflow Process (20% of the application) is dynamically loaded. Any changes to varied workflow Process will have no impact on the Core Workflow Process (80% of the application). Regression testing, Duration/cost for Onboarding of tenants is minimal. Externalization of Business rules, Multitenancy for applying business rules is also the point of focus here.
- Pain points with multiple application ·
- Large amount of redundancy and little reuse
- Enhancements and maintenance as the code changes done in multiple versions
- Multiple delivery/support teams performing similar work
- High TCO for multiple platforms
- High cost tenant on boarding
- Tenant on boarding is not quick
- Multiple IT support team
- Regression testing required for all tenants even if the change is limited to one tenant
Dynamic Process Flows
- Tenant specific workflow process
- One assembly for each Tenant with varied process definitions
- Externalizing the process-invoke decision, independent of the workflow assemblies
- Independent Deployment of Tenant Varied assemblies
- Dynamic load and invoke of the varied assemblies based on Metadata
- Metadata driven workflow processes
- WWF 4.0 and WCF 4.0 features utilized
- Workflow processes defined with WWF 4.0
- WCF Interception and service definition
Dynamic Business Rules
- Tenant specific Business rules
- Rules versioning
- Loosely coupled Business rules
- Deployment of Rules definitions for each Tenant to database
- Metadata driven Business Rules
- Dynamic load and execution of rules
- Windows application to define rules
- WWF Business Rules Engine to execute rules
Suggested Approach ·
Approach 1: Workflow as a service, which is a new feature in WWF 4.0 is used. This workflow is orchestrated to load the core workflow Process and the Varied Workflow Process for Tenants. But this had a limitation in WWF 4.0 hence the approach was dismissed. The limitation was – WCF Interception cannot be implemented across the client and the workflow service to intercept the tenant ID. This limitation has been corrected in WWF 4.5. ·
Approach 2 (considered): WCF service is implemented to load the Core workflow process and the Varied Workflow Process using WWF 4.0. Varied workflow Processes are loaded dynamically based on the tenant Id. The Tenant ID is intercepted from the client across the WCF services (that Invokes Workflow Process) and also the other WCF services that are consumed in the workflow orchestration.
The Business Rules are executed from WCF services that are invoked from the Workflow Process using WWF Business Rules Engine (BRE). The Business Rules definitions are dynamically loaded from DB based on the Tenant ID. Hence the loosely coupling of the rules are achieved.
- Multitenancy WCF Service: The client calls are made to the WCF Service, In the POC (Service Name- FacilityService, Method – CreateFacility). The Tenant ID is passed via WCF Interception. The service has references to dll – MetadataFetch, VariedProcessLoader.
Note: The Service is AspNet Compatibility enabled to utilize the asp.net caching.
- Metadata Fetch: This is a .NET assembly which communicates with the SQL database to obtain the metadata based on the Tenant ID to decide whether a Core Workflow Process needs to be invoked or a Varied Process. If a particular Tenant has metadata (Tenant mapping for the Namespace and ClassName (Workflow Process Name)) then that particular Varied Process is loaded else a Core Workflow Process in invoked.
- Varied Process Loader: This is a .NET Assembly. If the MetadataFetch Assembly returns the Namespace and ClassName (Workflow Process Name) for a particular Tenant. Then relevant Varied Workflow Process assembly is loaded and invoked) with appropriate input.
- Core Workflow Process (.NET Assembly): This is a .NET Assembly which contains the XAML files (workflow process definitions). If any tenant do not have a specified varied process defined, then default relevant core workflow process is invoked.
- Varied Workflow Process (.NET Assemblies): These are .NET Assemblies which contains the XAML files (workflow process definitions). Each Tenant that has any varied workflow process, is defined in a single assembly i.e. each tenant one assembly. Each Assembly will contain multiple XAML definitions based on the requirement. These assemblies (dll) are deployed to a folder (here -“D:\DeployedXaml”) from where the Varied Process Loader loads the assembly dynamically and invokes the appropriate workflow.
- Consumption WCF Services: These are multiple WCF Services. (Here there are 3 services – FacilityValidation, IncomeTax, and SalaryDetails). These implement business rules. SalaryDetails invokes the business rule via Workflow Business Rules Engine.
- External rule set Service: This is a workflow business rules execution component.
This contains the Rule Editor to create / modify rules. Rule set (rule definitions) are saved into the database with details like Major version (Tenant), minor version. Rules are created on a Target object (Client) which is defined in the Rules Library here. ExternalRuleSetService would fetch the Rule set definition from database and execute them using them using the Workflow BRE API. The Target object assembly (dll) is deployed to a folder (here - “D:\DeployedXaml”) which the Rule set refers to.
- WCF Interception: The Tenant ID is intercepted across the application using WCF Interception.
Note: Asp.NET caching is used to store it within the service.
Using the Code
After extracting the files, the following configuration is required:
- Create folder in D:\DeployedXaml: This is the path for folder to deploy the dll (Varied Workflow Process, Rules Library)
Note: This is configured in the Project properties-> Build Post Build Events.
In Order to change the path, Please make appropriate changes in the Project Properties and also in the configuration files (web.config or app.configs for the key “XamlPath”)
- All the Consumption services (WCF services) that are deployed, path has been updated in the Configuration (Web.config) file of the client consuming the services.
- Configure the database – Either the: Rules mdb and log files can be used or Create a database named “Rules” then Run the Attached database scripts in SQL Management Studio.
- MulitenancyWorkflowService project: web.config contains the db configuration for any further modification.
- Run the application, Use the values specified in the attached document here
Attached are the scenarios executed as part of testing.
- WCF Service (
MulitenancyWcf): The client calls are made to the WCF Service. This service invokes “
CreateFacility” workflow process (either a Varied or Core based on the Tenant ID).
- Service Name:
- Operation Name:
- Request Data Contract:
FacilityRequest Object, This is defined in the
- Response Data Contract:
FacilityResponse Object, This is defined in the
- Configuration: Web.config
RuleSetStoreConnectionstring: Has database connection string configuration
- Services/Bindings: Sections have WCF Interception and WCF service consumption related configurations
aspNetcompatibility mode enabled which enables the ASP.NET caching
<add name="RuleSetStoreConnectionString" connectionString="Initial Catalog=Rules;
Data Source=localhost;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true"/>
Core Workflow: This is a .NET assembly containing the workflow definition files (XAML) for all the default or core workflows. These workflows are invoked for all Tenants which do not have a varied workflow process defined. This dll is referred in the Multitenancy WCF Service.
The above is the project for Coreworkflows, Current POC has core workflow defined (CreateFacility.xaml). CreateSecurity and UpdateSecurityStatus are just empty workflow files. The above is the CreateFacility workflow definition, this workflow definition calls 3 WCF Services –FacilityValidation, SalaryDetails and IncomeTax. Based on output from the WCF service, the Workflow response is created.
Varied Workflow: These are .NET assemblies containing the varied workflow definition files for each Tenant. Each Tenant has a single assembly where a varied workflow process is defined if a variation exists.
Below is the project structure for varied workflow processes. Each Tenant has a set of varied process. For
Tenant1 – (
CreateFacility is the varied workflow process,
UpdateSecurityStatus is just a crude sample to show that multiple varied workflow processes can be added to a single Tenant.
Tenant2 – (
CreateFacility is the varied workflow process defined.
Tenant3 – (
WorkflowTenant3) – does not have a varied workflow process for
Note: A varied workflow process exists only when a Core workflow process is already defined for the same.
- Datacontract Library: This is a .NET Assembly that is referenced across all projects. This has
Datacontract (request and response) defined for the WCF service and also the workflow processes as follows.
Activities: Data Contract library also contains Code Activities that is used in the workflow definitions where the input is manipulated (data type conversion) and the response is created.
Decision Library: This is a .NET assembly which has classes to deal with metadata workflow decision and also varied workflow process loader.
Metadata Fetch: This is a .NET assembly which communicates with the SQL database to obtain the metadata based on the Tenant ID to decide whether a Core Workflow Process needs to be invoked or a Varied Process. If a particular Tenant has metadata (Tenant mapping for the Namespace and ClassName (Workflow Process Name)) then that particular Varied Process is loaded else a Core Workflow Process in invoked.
Varied Process Loader: This is a .NET Assembly. If the Metadata Fetch Assembly returns the Namespace and ClassName (Workflow Process Name) for a particular Tenant. Then relevant Varied Workflow Process assembly is loaded and invoked with appropriate input.
- Service Interceptors: The WCF interception is implemented by implementing the
IDispatchMessageInspector.AfterReceiveRequest(ref Message request,
IClientChannel channel, InstanceContext instanceContext)
AfterReceiveRequest event extracts the Tenant ID from the message body and saves the same in ASP.NET session which is further used in the Services.
NOTE: They involve relevant configuration (App.config/web.config) changes.
- Client Interceptors: The WCF interception is implemented by implementing the
IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request,
BeforeSendRequest event is called before any request that is made to the service. Here Tenant ID is extracted from the current ASP.NET session and hence the Tenant ID is passed in the Message Header.
NOTE: They involve relevant configuration (App.config/web.config) changes.
Consumption Services: These are WCF services which are consumed by the Workflows.
FacilityAmount that is input from client is verified against an amount using
GetFacilityValidationAmount operation from
FacilityValidation Service. Based on the
facilitytype the validation amount is returned.
GetClientSalary operation from
SalaryDetails service is called. Here, Business Rules, that is defined using Workflow Rules Editor, is executed. The business rules can be edited independent of the WCF service. Any changes to the rules, does not impact this WCF service in terms of deployment.
VerifyTax operation is called to verify tax. The Business rule is just coded here.
ExternalRuleSetLibrary: This is just a data entity for rules set information that is accessed from database. ·
ExternalRuleSetService: This contains classes that communicate with database to obtain the Rules set based on the Rule set name specified, Tenant ID/Major Version, minor version. This also contains class to execute the rules using WWF 4.0 BRE API. ·
RulesLibrary: This contains the entity class or Target object on which the Rules are defined. ·
ExternalRuleSetTool: This is an interface to create /modify rules. This tool saves the rules definition in the database.
The Rules Editor seen below is from the following link: http://msdn.microsoft.com/en-us/library/bb472424.aspx
From the Rule Store menu, you can load the available RuleSets from the database and save modified RuleSets back to the store. An application configuration file provides a database connection string for the RuleSet database. When you start the tool, it automatically loads the RuleSets from the configured database.
The RuleSet tool applies major(here Tenant ID) and minor version numbers to the RuleSets, allowing you to simultaneously maintain and store multiple versions (the tool provides no locking or other configuration management features in addition to the versioning capability). Using the tool, you can create new RuleSet versions or delete existing versions. When you click New, the tool creates a new RuleSet name and applies version 0.0. When you copy a version, the tool creates a copy of the selected RuleSet version, including the contained rules, and assigns new, unique version numbers. These version numbers are based on the version numbers of existing RuleSets. You can change the RuleSet name and version numbers using the associated fields on the form.
NOTE: Version 0 – would be the default RuleSet which is executed if no mapping for Tenant exists in the Database.
When you click Edit Rules, the RuleSet editor starts, as shown in below figure
This is a re-hosting of the editor dialog that is part of the Windows Workflow Foundation Visual Studio add-in. It provides the same functionality, including Intellisense support. The rules are authored against a target type (such as a workflow) that is associated with the RuleSet in the tool; when you click Browse in the main tool dialog, the Workflow/Type Selector dialog appears, as shown in below figure.
You can use the Workflow/Type Selector dialog to specify an assembly and a specific type within that assembly. This type is the target type against which the rules are authored (and run). In many cases, the target type is a workflow or some other activity type. However, you can run a RuleSet against any .NET type.
The path to the assembly file and the type name are stored with the RuleSet in the database, so that when the RuleSet is retrieved from the database, the tool attempts to automatically load the target type.
When you click OK in the Workflow/Type Selector dialog, it validates the selected type against the RuleSet, to ensure that the target type has all the members referenced by the rules.
For further details of the tool please refer to the link mentioned above.
TenantAssemblyMap – This table has the data where Tenant is mapped to varied workflow processes (Assembly)
Tenant- This table has the Tenant name and Id.
AssemblyDetails - This table has names of the assemblies which contain definition for the workflow processes for each tenant. This is the workflow Metadata required to invoke the workflow process.
NamespaceDetails – This has names of the Namespaces details of the workflow processes defined in the assemblies. This is also the workflow Metadata required to invoke the workflow process.
ClassDetails – This has names of the class details of the workflow processes defined in the assemblies. This is also the workflow Metadata required to invoke the workflow process.
- Rule Set – This table has the rules definition with version. The
MajorVersion column in the table is the TenantId.
Points of Interest
The point of interest would be the entire Multitenancy concept. There are several patterns used to achieve the same. We have tried to achieve this using Microsoft tools.
Sundararajan Thyagarajan who also works at Infosys Technologies, suggested this idea on Multitenancy. This was based on several requirements on Multitenancy in one of the leading Insurance projects. Further research might be required in terms of performance benefits of the approach and also on Comparison study if the Multitenancy concept can be achieved using MEF composition. Further research is also required on the Approach 1 described in the article which failed due to limitations in WWF 4.0.