<style>
.reveal {
font-size: 32px;
}
</style>
---
### Documentum - Purpose
- Manage unstructured information using relational databases
- A custom system to organize, store, maintain, selectively publish Boeing 777 training manuals
- A custom system for Syntex that: "automate the process of assembling New Drug Application (NDA) documents when seeking approval from the U.S. Food and Drug Administration (FDA)"
---
### History
- Founded 1990 by two database guys
- Released 1993 as **Electronic Document Management System (EDMS)**
- Bought by EMC in 2003
- EMC merged with DELL in 2016
- OpenText buys Documentum from DELL EMC in 2017
- Runs on many versions of Unix and Windows.
---
### Product Family
```graphviz
graph grid {
node [shape=box style=rounded]
subgraph cluster_b {
style=rounded
label=Backend
C [label="Documentum (Content) Server"]
J [label="JMS/iJMS"]
S [label="Storage/Database"]
B [label="Docbroker"]
}
subgraph cluster_c {
style=rounded
label="Helper Services"
R [label="Content Transformation Service"]
T [label="Thumbnail Server"]
I [label="Index Server"]
E [label="DCTM Rest"]
}
subgraph cluster_a {
style=rounded
label=Frontend
W [label=Webtop]
D [label=D2]
X [label=xCP]
}
// Grid stuff
edge [weight=1000 style=invis]
W -- C -- J -- S -- B
X -- I -- T -- R -- E
}
```
---
### Storage model
```graphviz
digraph {
A [label="Content Server" shape=box style=rounded]
C [label="Database" shape=cylinder]
B [label="File Storage" shape=folder]
A -> { C B }
}
```
---
### Classic API
- Mostly deprecated
- Low level
- Usable from command line (iapi.exe) if no frontend available
- Accessable using DA
Example:
```
API>get,c, 09001be6836483d3, dosage
1mg
API>set,c, 09001be6836483d3, dosage
SET>2mg
OK
API>save,c, 09001be6836483d3
API>dump,c, 09001be6836483d3
...
USER ATTRIBUTES
object_name : 01 - Beslut
dosage : 2mg
```
---
### DFC
- Java API
Example:
```Java=1
var obj = session.getObject( new DfId( "09001be6836483d3" ) );
var dosage = obj.getString( "dosage" );
obj.setString("2mg");
obj.save();
obj.dump();
```
---
### DQL
- Custom extention to SQL
- A collection of questionable design decisions
Example:
```SQL=1
SELECT object_name, dosage
FROM mp_licence_decision
WHERE r_object_id = '09001be6836483d3'
UPDATE mp_licence_decision
OBJECT SET dosage='3mg'
WHERE r_object_id = '09001be6836483d3'
```
---
### DQL: the Good, the Bad, the Ugly
- Good
- Powerful (affect many objects at once)
- Reasonably fast
- Bad
- No precompiled statements (not Injection-safe!)
- Unpredictable SQL, hard to optimize
- Ugly
- Repeating attributes
- Oh, dear God, the repeating attributes
- ENABLE(hint_list) (also mostly about repeating attributes..)
---
### DCTM-Rest
- Interact with documentum without knowing much about documentum.
- Not installed in all environments
Example:
```json
GET https://server/dctm-rest/repositories/dbDOCp01/objects/09001be6836483d3
"name": "object",
"type": "mp_licence_decision",
"definition": "https://server/dctm-rest/repositories/dbDOCp01/types/m_licence_decision",
"properties": {
"object_name": "01 - Beslut",
"dosage": "2mg",
}
```
---
### Important concepts
- Objects
- Data model
- Workflows
- Lifecycles
- Server methods
- BOF - TBO - SBO
- Jobs
---
### Objects
- Typed, e.g. dm_document, mp_base_doc
- Has attributes
- Single or Repeating
- Itself typed (e.g. STRING, INT, BOOLEAN, DATE)
- Inherits from supertype
---
### More about Objects
- Versioned with 'i_vstamp' attribute
- Persistent (almost all types)
- Uniquely identified within docbase
---
### Object ID
- Object IDs are hexadecimal strings exactly 14 characters long
- E.g. **001be6836483d3**
- Object IDs have in three parts
- Object type: **09** 001be6836483d3
- Docbase ID: 09 **001be6** 836483d3
- Object ID: 09001be6 **836483d3**
- 32 bits
- 4 billion possible objects
- Common types:
- 08 DM_SYSOBJECT
- 09 DM_DOCUMENT (Even inherited types)
- 0b DM_FOLDER
- 4d DM_WORKFLOW
---
### Modifications and Concurrency
- Optimistic locking
- DM_SYSOBJECT_E_VERSION_MISMATCH or DM_OBJ_MGR_E_VERSION_MISMATCH
```
[DM_SYSOBJECT_E_VERSION_MISMATCH]error: “save of object failed because of version mismatch: old version was 30”; ERRORCODE: 100; NEXT: null
```
---
### Object Content
- Objects may have content
- Attached document (any file format)
- Multiple formats
- Known formats get special treatment (.docx, .pdf, .msg)
- May be visible in folder hierarchy
- Can be
- Viewed: Downloaded and presented to user
- Checked out: Downloaded and modified
- Checked in: Modification saved and versioned
- Checkout aborted: Modifications discarded
- Versioned
- 0.1, 1.0, CURRENT
- May branch
- New version created by checking in
---
### Content Transfer
- In custom application:
- Downloaded using DFC/Rest/Other
- Checkout and Download is different operations
- In browser frontend (DA, D2, STEP)
- Downloaded through browser extension
- Viewed files goes to Documentum/Viewed
- State saved in Documentum/temp/.viewed.xml
- Checked out files to Documentum/Checkout
- State saved in: Documentum/Checkout/.checkout.xml
---
### Data model
```mermaid
graph TD;
%% Defining nodes is not necessary but nice to have
%%
%% Documentum base types
%%
subgraph Documentum_base_types
Persistent
dm_sysobject
dm_folder
dm_document
dm_cabinet
dm_relation
end
%%
%% Types defined in MPA_GENERAL. Are these not used?
%%
%%
%% m_base_cabinet
%% m_base_doc
%% m_base_folder
%% m_base_link
%% m_base_product
%%
subgraph Läkmedelsverket_types
%%
%% Types defined in MPA_LV
%%
mp_base_doc
mp_base_folder
mp_config
mp_diary_cabinet
mp_diary_container_folder
mp_diary_folder
mp_diary_plan_folder
mp_general_diary
mp_general_record
mp_record_doc
mp_relation
mpa_record_type_config
%%
%% Types defined in MPA_LISY
%%
mp_producttype_text
mp_consulting_reason
mp_decision_data
mp_decision_reason
mp_licence_record_config
mp_license_diary
mp_license_diary_shadow
mp_license_record
mp_supplement_reason
mp_license_motivation
mp_licence_consultation
mp_licence_decision
mp_license_application
mp_supplementing_request
end
%%
%% Inheritance relations
%%
Persistent --- dm_sysobject
Persistent --- dm_relation
dm_sysobject --- dm_folder
dm_sysobject --- dm_document
dm_sysobject --- dm_cabinet
dm_sysobject --- mp_config
dm_sysobject --- mpa_record_type_config
dm_sysobject --- mp_producttype_text
dm_sysobject --- mp_consulting_reason
dm_sysobject --- mp_decision_data
dm_sysobject --- mp_decision_reason
dm_sysobject --- mp_supplement_reason
dm_relation --- mp_relation
dm_cabinet --- mp_diary_cabinet
dm_folder --- mp_base_folder
dm_document --- mp_base_doc
mp_base_doc --- mp_record_doc
mp_base_folder --- mp_diary_container_folder
mp_base_folder --- mp_diary_folder
mp_base_folder --- mp_diary_plan_folder
mp_diary_folder --- mp_general_diary
mp_diary_folder --- mp_license_diary
mp_record_doc --- mp_general_record
mp_record_doc --- mp_license_record
mpa_record_type_config --- mp_licence_record_config
mp_license_diary --- mp_license_diary_shadow
mp_license_record --- mp_license_motivation
mp_license_record --- mp_licence_consultation
mp_license_record --- mp_licence_decision
mp_license_record --- mp_license_application
mp_license_record --- mp_supplementing_request
```
---
### Lifecycles
```graphviz
digraph {
node [shape=box style=rounded]
rankdir=LR
Draft -> Open -> Established
edge [style=dotted]
Established -> Open -> Draft
}
```
- Describes an objects state
- **Promote** forwards, **demote** backwards
- No skipping!
- Specific to a set of types
- Can define entry criteria
- Changes may trigger code execution
- One object can only be attached to one lifecycle
- Persistent
---
### Workflows / Processes
- Lifecycle's big brother
- Formalizes and controls collaboration on complex tasks
- Built up of states called "activities"
- Automatic
- Manual
- Has associated objects in a "package"
- Has one start and one end state
- Read the Fundamentals Guide!
---
### Workflows example (simplified)
```graphviz
digraph {
node [shape=box style=rounded]
rankdir=LR
rank=same { Manage Consultation ExternalConsultation }
rank=same { RequestSupplement AwaitSupplement}
Manage -> RequestSupplement -> AwaitSupplement -> Manage
Start -> Manage -> CreateDecision -> SendDecision -> End
Manage -> Consultation -> Manage
Manage -> ExternalConsultation -> Manage
edge [style=dotted]
}
```
---
### More on Workflows
- State transitions on:
- Timers
- User action
- Integration activity
- Triggered actions:
- Server method calls
- Send mail
- "Create" queue items
---
### Workflow queue items
- Manual activities has associated queue items
- Represents a task to be performed
- Has one(or more) responsible user(s)
- Has an assigned priority
- Has it's own state transisions
```graphviz
digraph {
node [shape=box style=rounded]
rankdir=LR
rank=same { Dormant Paused }
rank=same { Acquired DAP }
Dormant -> Acquired [label=Acquire]
Acquired -> Dormant [label=Reassign]
Acquired -> Finished [label=Complete]
Dormant -> Paused -> Dormant
edge [style=dotted]
Paused -> DAP -> Paused
Dormant -> DAP -> Dormant
Acquired -> DAP -> Acquired
}
```
---
### Processes
- The new black
- Can be stateless or stateful
- Defined using xCP designer (not Process Builder)
---
### BOF - Business Object Framework
- Loads code from content server "modules"
- Execute code locally or remotely
- Code can be updated at runtime (but may be cached)
- Java Interface must be awailable at client compile time
---
### Server methods
- Execute code on Java Method Server (JMS or iJMS)
- Can be called from workflows and life cycles
Example:
```Java=1
IDfList arguments = new DfList();
IDfList dataTypes = new DfList();
IDfList values = new DfList();
arguments.appendString("METHOD");
arguments.appendString("ARGUMENTS");
arguments.appendString("LAUNCH_ASYNC");
dataTypes.appendString("S");
dataTypes.appendString("S");
dataTypes.appendString("B");
values.appendString(methodName);
values.appendString(sb.toString());
values.appendString("T");
col = docbaseSession.apply((String)null, "DO_METHOD", arguments, dataTypes, values);
```
---
### TBO - Type Based Objects
- Modifies object operations using Java
- Save
- Checkin
- getString
- promote
- ... Many More
- Executes in content server
---
### SBO - Service-based Business Object
- Executed locally (in application server)
Example:
```Java=1
ILicenceServiceSBO service = (ILicenceServiceSBO)client.newService(ILicenceServiceSBO.class.getName(), sessionManager);
service.setSporkEndpointUrl(props.getSporkEndpointUrl());
```
---
### Jobs
- Schedule server method calls.
- Typically used for reports and maintenance routines
---
### Dev Tools: Composer
- Defines
- Types
- BOF Modules (SBO/TBO)
- Lifecycles
- Folders, Groups, Sysobjects
- ... More things
- Creates and Updates customizations
- Horribly frustrating
---
### Dev Tools: Process Builder
- Defines Workflows
- Deprecated ?
---
### Dev Tools: DA
- Default admin tool
- DQL executor
- API Tester
- Workflow monitor
- Job management
- User Management
- ... More
---
### Dev Tools: DQLBuddy
- Third party
- Provides DA capability
- Is faster on some things
---
### Dev Tools: Our own
- Standalone: Loke tool to work with STEP things
- CLiVe: Pontus tool to work with LISY things
{"metaMigratedAt":"2023-06-17T07:20:17.218Z","metaMigratedFrom":"YAML","title":"Documentum","breaks":true,"slideOptions":"{\"theme\":\"solarized\"}","contributors":"[{\"id\":\"88c8cdb7-ca65-4bbd-8909-1e506f916780\",\"add\":17518,\"del\":5463}]"}