Findings of the SAP Mobiliser 5.1 data model: #1 – multi-tenant capable?
I’m currently participating in a bootcamp on SAP Mobiliser 5.1. During this learning phase, I’m stumbled about some questions or topics which need further explanation and/or or expert’s enlightenment. Perhaps these are typical beginner’s understanding problems.
I’ll try to compile these topics in this blog series.
Please see also my other Mobile blogs.
Data Model and Data Access Objects
I’ve read about the Mobiliser data model and performed the first steps in development. The related examples (Hands-On labs) are available here: http://scn.sap.com/docs/DOC-40367
Database tables are accessed using the Java framework Hibernate: typically DAO (Data Access Object) classes will be used to query the database. These classes will provide methods like:
If using a getById query, the given ID is the primary key (a single column). The resulting WHERE statement won’t contain a tenant/org-unit/client related criterion.
#1 – Multi-tenant capabilities
SAP Mobiliser claims to be multi-tenant capable, see for example this excerpt from the document Money_Mobiliser_5.1_Architecture_and_Businesslogic.pdf:
2.1.9 Table MOB_ORGUNITS
Lists the org-units where entities can belong to – provides multi-tenancy to the system.
Usually for each new Mobiliser installation one or multiple org-units are created. The org-unit is the way to
handle multiple tenants in one system. Business rules can be configured based on the org-unit that is assigned
to a customer. Usually, a customer is created in an org-unit and this org-unit is never changed. The org-unit
Definition in Wikipedia
Multi-tenancy vs. client-capability
Is there a difference between multi-tenancy and client-capability?
Principle of software architecture in which a single software instance c an run for multiple tenants on a single application server. In a multitenancy AS ABAP, application clients are the tenants.
The related definition of Client is:
Organizational unit in AS ABAP. Each logon to AS ABAP must include a client ID. This ID indicates a logon to a specific client. The various clients in an AS ABAP have separate user master records and separate authorizations. Client-specific data is split by the client column in application tables. Application programs generally run in application clients. Alongside these, a system client and optional administration clients are used to run system-specific or administration tasks. On an AS ABAP that supports multitenancy, tenants are mapped to clients.
As being both Java and ABAP developer, this summarizes my understanding of the traditional SAP Business Suite: each client-specific table has a column “CLIENT” (or MANDT). This matches with above statement:
Client-specific data is split by the client column in application tables.
This CLIENT (or MANDT) column will be the first part of the table’s composed primary key (exception is table T000 – there it’s the only key).
In ABAP, the current client will be used for any database query automatically – unless it’s a non-client specifc table or the CLIENT is specified explicity using ABAP keywords. The later case will be logged in the system protocol and AFAIK could be switched off. So a strict separation of client-specifc records is given by the ABAP runtime framework.
If using Hibernate, a typical primary key query will use a single ID value – there exists no concept of automatically adding the current CLIENT. So it would be possibly (by program error or by malicious code) to read master data of a different tenant (org-unit).
For a simple example of the problem, let’s take the Mobiliser table MOB_ERROR_CODES:
/*==============================================================*/ /* Table: MOB_ERROR_CODES */ /*==============================================================*/ create table MOB_ERROR_CODES ( ID_ERROR_CODE NUMBER(5) not null, ID_ERROR_LEVEL VARCHAR2(80 char) not null, STR_INFORMATION VARCHAR2(200 char) not null, DAT_CREATION TIMESTAMP, ID_CUSTOMER_CREATION NUMBER(18), DAT_LAST_UPDATE TIMESTAMP, ID_CUSTOMER_LAST_UPDATE NUMBER(18), constraint PK_ERROR_CODES primary key (ID_ERROR_CODE) )
As ID_ERROR_CODE is the primary key, this means that two tenants cannot have the same error code (e.g. 10001) with different meaning. The normal workaround would be to separate the tenants by a number range, e.g. tenant 1 error codes are in the range 10000-19999, tenant 2 in the range from 20000-29999 and so on.
This is only a simplistic example, but it shows the problem with the missing CLIENT column. (As a side note: the error text isn’t multi-language capable – no language indicator, not of type Unicode).
There exist several tables which have a column ID_ORGUNIT defined and this is in fact a starting point. And I’ve read about the programming logic where first this column is checked for an exact match and afterwards a test on “null” is performed.
This logic is described for example in the description of column ID_ORGUNIT of table MOB_CUSTOMERS_IDENTIFICATIONS (chapter 2.1.5):
The org-unit this identification belongs to. This field is optional, and we check that the combination of STR_IDENTIFICATION and ID_ORGUNIT is unique. Also, if the org-unit field is filled for identifications, any Mobiliser service calls passing in an identification must also fill the org-unit field in order to match.
In ABAP, the CLIENT column never could be “null” or initial as it’s part of the primary key.
In my opinion, the multi-tenancy concept in SAP Mobiliser can’t be compared to the traditional ABAP data model of client-capability:
- less powerful – no built-in separation of records
- cannot restrict reading (changing?) other tenant’s records
- less performant – no primary key query
I’m interested in your feedback about this topic – especially whether this caused any trouble in real-world projects.
The next blog in this series will be about the grouping of customers.