Saturday, December 3, 2011

Error while creating a copy of ACL template in DFC

If you try to create a copy of an ACL template (which has alias references) using the method saveAsNew(), you will receive an error like this:
2011-12-02 11:53:01,138 ERROR [main] com.mycompany.documentum.job.method - [DM_ACL_E_USER_NOT_EXIST]error: "The owner_name or accessor_name '%alias' given in the ACL 'myACL' does not exist."
DfException:: THREAD: main; MSG: [DM_ACL_E_USER_NOT_EXIST]error: "The owner_name or accessor_name '%alias' given in the ACL 'myACL' does not exist."; ERRORCODE: 100; NEXT: null

This is caused by a bug in DFC method saveAsNew() of DfACL - it does not copy the value of attribute acl_class, which defines the ACL type (template, regular, etc.)

So you have to make a clone with custom code, something like this:

public IDfACL cloneACL(IDfACL acl, String name) throws DfException {
IDfACL copy = (IDfACL) acl.getSession().newObject("dm_acl");
copy.setObjectName(acl.getObjectName());
copy.setDescription(acl.getDescription());
copy.setString("owner_name", acl.getString("owner_name"));
copy.setACLClass(acl.getACLClass());
for (int i = 0; i < acl.getAttrCount(); i++) {
if (acl.getAttr(i).isRepeating()) {
String attrName = acl.getAttr(i).getName();
for (int j = 0; j < acl.getValueCount(attrName); j++) {
copy.setRepeatingValue(attrName, j, acl.getRepeatingValue(attrName, j));
}
}
}
copy.save();
return copy;
}

Friday, November 25, 2011

How to change a single attribute to repeating

There's no direct way to change a single attribute to repeating in your custom types, so this task is not trivial if you already have objects with metadata that should be preserved: a temporary attribute must be used.
The safe way is to perform the following steps:


1. Ensure no objects of your type are locked: select * from my_type where r_lock_owner <> ' ' (if you have locked objects, you should unlock them - see how to unlock).
2. Create a temporary single attribute fake_attr: alter type my_type add fake_attr char(100) publish
3. Copy all the values from your single attribute to the temporary one: update my_type objects set fake_attr=my_attr
4. Remove the single attribute: alter type my_type drop my_attr publish
5. Add the repeating attribute: alter type my_type add my_attr char(100) repeating publish
6. Copy back the metadata: update my_type objects append my_attr=fake_attr

Wednesday, November 23, 2011

How to restart correctly the repository (Content Server services)

A typical Content Server contains 3 types of services: Docbroker, Docbase and JavaMethodServer. The correct restart procedure is:

Change the startup type to 'Disabled' and stop the services:
1. JMS service
1a Check for java.exe process (use ProcessExplorer): if found, ensure it's related to JMS and kill it (sometimes it hangs and doesn't terminate when you stop JMS).
2. Docbase(s) service(s) (if there are more than 1 Docbase, stop them one by one, the global repository must be the last).
3. Docbroker(s) service(s).
4. Clean the JMS cache ([JBOSS]\server\DctmServer_MethodServer\work\) and DFC(BOF) cache (DM_HOME\dfcdata\cache)


Change startyp type to 'Auto' (or Manual) and start the services:
5. Docbroker(s)
6. Docbases (if you have more, start the global repository first, then the others)
6a Check each started docbase log for errors
7. JMS
7a Check JMS logs ([JBOSS]server\DctmServer_MethodServer\log): boot.log and server.log

Tuesday, November 22, 2011

How to create and modify an ACL with API

An ACL can be created using Composer, DFC code, or an API command. Here's a sample of creating and modifying an ACL with API:

create,c,dm_acl
set,c,l,object_name
sample_name
set,c,l,owner_name
dm_dbo
set,c,l,description
Sample ACL
grant,c,l,dm_world,6
grant,c,l,dm_owner,7
grant,c,l,sample_groupA,3
save,c,l


If you wand to modify an existing ACL, you can use:
retrieve,c,dm_acl where object_name = 'sample_name'
revoke,c,l,sample_groupA
grant,c,l,sample_groupB,3
grant,c,l,sample_groupC,7
save,c,l

Sunday, November 20, 2011

How to unlock an object in Documentum

When a user makes a checkout on a sysobject (opens to edit), Documentum automatically applies a lock on the object, preventing other users from modifying it. Only the lock owner or a superuser can unlock the object by making a checkin or cancel the checkout. As sometimes users forget to unlock documents, you might need to do this as a superuser.
You can unlock an object in 2 ways:

DQL:
update dm_document object set r_lock_owner='', set r_lock_machine='', set r_lock_date=date('nulldate') where r_object_id='[OBJECT_ID]'
API:
unlock,c,[OBJECT_ID],F
The last argument is a boolean flag specifying if a mail notification will be sent to the lock owner.

Saturday, November 19, 2011

xPlore Index Agent login failure

If you are using Documentum xPlore for fulltext search, you might face the following issue: after starting the Index Agent process, you have to start the Index Agent from the Administration page (http://URL:port/IndexAgent/login_dss.jsp), but the login fails with the message:
User is not an Admin User!
even if your user is a superuser

The cause is a bug in the login_dss.jsp code:
IDfUser userObject = doc_session.getUserByOSName(uname, domain_name);

if (userObject != null)
isSysAdmin = userObject.isSysAdmin();

The bug here is that if the userObject is null (was not found), the flag isSysAdmin remains false, so the error message doesn’t say that the user was not found, instead you have the message above telling it’s not an Admin user.

Now why the userObject can happen to be null? (Note: at this point of code the user is already logged in against the repository). It’s because the user is searched using getUserByOSName(uname, domain_name) method. So if the user_os_domain is not set in the dm_user object and the Documentum repository runs in domain required mode (dm_docbase_config.auth_protocol='domain_required') : if you don’t specify the domain on login page – login doesn’t succeed, if you specify it – the userObject is not found – thus null.

To solve this issue it's enough to modify the login_dss.jsp page substituting the getUserByOSName(uname, domain_name) method with getUserByLoginName(uname, domain_name) or getUser(uname), or you could just set the user_os_domain in the dm_user object (however first option is preferred).

Monday, November 14, 2011

Change repository owner password in Documentum

If the Database user password used for the Documentum repository is modified, you can update it accordingly in Content Server by following the steps:

1) Stop the repository service(s) (and all dependant services, ie: app servers)
2) Go to $DM_HOME/dba/config/
3) Create a copy of the file dbpasswd.txt
4) Edit the dbpasswd.txt and replace the old (encrypted) password with the new password, as plain text (not encrypted)
5) Save dbpasswd.txt
6) Go to $DM_HOME/bin and run the following command: dm_encrypt_password -docbase -rdbms -encrypt
7) Open the dbpassword.txt file (created at step 4-5) and check if the password has been encrypted
8) Restart repository service(s) (and other dependant services)
9) Check the repository log if it started successfully

Tuesday, June 28, 2011

Configure the second Content Server for the repository

If you have a multiple-Content Server Documentum Infrastructure, you should install and configure manually the second Content Server instance. Assuming the first (main) CS is already installed and configured, below are the steps to install manually the second one (no wizzard). Ensure it will be on a different host machine (you can use a virtual one if you don’t want to buy a new box ;) ).

1) Connect to the repository as the installation owner by using Documentum Administrator and create a new server config object (below sample values):
Name: CS_NAME_LB1
Web server location: [server name of the CS Workstation]
Web server port: 80
Locale name: en
Default client codepage: ISO_8859-1
Server OS codepage ISO_8859-1
SMTP server [smtp_dns]
Workflow Content
Migration Threads: 10
Maximum Login Ticket 43200
Default Login Ticket 5

* Set other settings to fit the first config object.

Update the owner name for the new created object using the DQL
update dm_server_config objects set owner_name = '[docbase_owner]' where bject_name='[object_name]'

Disconnect from the repository

2) Create a server.ini file for the new Content Server
Create the folder [docbase_name] in the following path on the new Content Server:
…\Documentum\dba\config

Copy in this folder ([docbase_name]) the server.ini file from the first Content Server, for this repository.

Change the server_config name
server_config_name = CS_NAME_LB1

and the docbroker configurations
[DOCBROKER_PROJECTION_TARGET]
host = [docbroker2]
port = 1489

[DOCBROKER_PROJECTION_TARGET_1]
host = [docbroker1]
port = 1489
proximity = 100

* if additional projections required (add as many as required):
[DOCBROKER_PROJECTION_TARGET_2]
host = [docbroker3]
port = [port]

3) Create the repository Windows service by running the following command file:
@echo off
setlocal

set docbase=[docbase_name]
set instowner=[installation_owner_user]
set iodomain=[domain]
set iopass=[password]

set binPath=E:\Documentum\product\6.5\bin\documentum.exe -docbase_name %docbase% -security acl -init_file E:\Documentum\dba\config\%docbase%\server.ini -run_as_service -install_owner %instowner% -logfile E:\Documentum\dba\log\%docbase%.log

sc create DmServer%docbase% binPath= "%binPath%" start= demand DisplayName= "Documentum Docbase Service %docbase%" obj= %iodomain%\%instowner% password= %iopass%

sc description DmServer%docbase% %docbase%_clone
endlocal

5) Configure port numbers

Edit C:\WINDOWS\system32\drivers\etc\Services file and add the following entries at the end of the file:
dm_[docbase_name] [prev+1]/tcp #Documentum Docbase Service [docbase_name]
dm_[docbase_name]_s [prev+1]/tcp #Documentum Docbase Service [docbase_name] (secure service)

6) Update the windows registry
* sample values used, set the ones from your system
[HKEY_LOCAL_MACHINE\SOFTWARE\Documentum\DOCBASES\[docbase_name]]
"DM_CONFIGURE_STATUS"=hex(2):43,00,6f,00,6d,00,70,00,6c,00,65,00,74,00,65,00,\ 00,00
"DM_AUTH_LOCATION"="[domain]"
"DM_DATABASE_NAME"=""
"DM_DOCBASE_CONNECTION"="[DB_TNS]"
"DM_DATABASE_USER"="[docbase_name]"
"DM_DATABASE_ID"="db_id"
"DM_SERVER_VERSION"="6.5 SP2"
"DM_HOME"="E:\\Documentum\\product\\6.5"
"DM_CONFIGURE_TIME"="Fri Jan 14 12:34:00 CET 2011"
"DM_SERVICE_NAME"="[service_name]"
"DM_RDBMS"="Oracle"
"DOCUMENTUM"="E:\\Documentum"

7) Copy the dbpasswd.txt and webcache.ini file from first CS to second CS, in following path:
…\Documentum\dba\config\[docbase_name]

8) Create the folder for the session log files
…\Documentum\dba\log\[docbase_name]

9) Start the docbase services on both content servers

10) Using DA create the dm_LogPurge_LB1 job, as a clone of dm_LogPurge. Set as designated server the second CS (the one installed now). Set other settings similar to original LogPurge job (method, arguments, etc.).

11) Advice: in a multiple-CS environment, it is recommended to set a designated server for each job (otherwise it can happen a job is started simultaneously on 2 CS). User job sequences, if necessary.

12) Create the ACS object for the second Content Server

dmbasic -fE:\Documentum\product\6.5\install\admin\dm_acs_install.ebs -eInstall – [docbase_name].[CS_name] [install_owner] [password] [server_host_name]ACS1 [CS_name] 9080 http F "" ]dm_acs_install.log

Update the acs.properties file with the newly created ACS object by adding in the properties file
…\[method_server_path]\deploy\acs.ear\APP-INF\classes\config\acs.properties
the entries for the new created object:
repository.name.i=[docbase_name].[CS_name]
repository.login.i=[install_owner]
repository.password.i=[password]
repository.acsconfig.i=[acs_config_object_name]
* i – number not used yet in this file settings

13) Start the JMS.

Test and enjoy!

Friday, May 20, 2011

Manage Folders with DQL

Create a folder and link it:
CREATE dm_folder object
set object_name='FolderName',
set owner_name='owner',
set acl_name='ACLName',
set acl_domain='ACLDomain'
link '/Path'

How to find empty folders in the entire docbase:
a)
select r_object_id, object_name, r_object_type, r_folder_path FROM dm_folder f WHERE r_object_id NOT IN (SELECT distinct i_folder_id FROM dm_sysobject WHERE any i_folder_id = f.r_object_id)
b)
select r_object_id, object_name, r_object_type, r_folder_path FROM dm_folder f WHERE r_link_count=0

Get count of documents by custom type for each folder:
select f.r_object_id, f.r_folder_path, d.r_object_type, count(d.r_object_id) FROM dm_folder f, dm_document d WHERE any d.i_folder_id=f.r_object_id group by f.r_object_id, d.r_object_type


How to find empty folders only in a cabinet?
SELECT r_object_id, object_name, r_object_type FROM dm_folder f WHERE r_object_id NOT IN (SELECT distinct i_folder_id FROM dm_sysobject WHERE any i_folder_id = f.r_object_id AND FOLDER(‘/cabinet_name’, DESCEND)) AND FOLDER(‘/cabinet_name’, DESCEND)

Queues Management with DQL

1. FullText Queue

Objects in FullTextIndex queue (requsts for fulltext indexing):
select name,task_state,count(r_object_id),min(date_sent) from dmi_queue_item where name like '%index%' and dequeued_date is nulldate group by name,task_state order by name,task_state

Object types registered for indexing:
select name from dm_type where r_object_id in (select distinct registered_id from dmi_registry where user_name like '%fulltext%')

Resubmit items to FullTextIndex queue:
update dmi_queue_item objects set task_state=' ', set sign_off_user=' ', set message=' ', set dequeued_by=' ', set date_sent=DATE(NOW) where name like 'dm_fulltext_index_user%' and task_state='failed'


Remove items with warnings from FTI queue:
delete dmi_queue_item objects where name like 'dm_fulltext_index_user%' and task_state='warning'


2. Renditions (Content Transformation) queue

Objects in CTS queue (requests for rendition creation):
select * from dmi_queue_item where event='rendition'

Documents which don’t have a rendition:
select * from dm_document where r_object_id not in (select parent_id from dmr_content where rendition>0)

Renditions generated today:
select * from dmr_content where rendition>0 and set_time > DATE(TODAY)

Manage custom types with DQL

I. Create custom type
CREATE TYPE "custom_document"
("booleanAttr" bool REPEATING,
"integerAttr" integer,
"commentAttr" string(10),
"numberAttr" string(20),
"idAttr" id,
"dateAttr" date,
"doubleAttr" double,
"charAttr" CHAR(20))
WITH SUPERTYPE dm_document
publish;

II. Modify custom type
General tab settings
alter type custom_type
set label_text = 'Title' ,
set help_text = 'some hint' ,
set comment_text = 'some comment'
set DEFAULT BUSINESS POLICY='dm_policy.r_object_id' VERSION 'NONE'
SET DEFAULT STORAGE='filestore_01'
Display configuration
a) “Display Configuration” tab (for webtop application)
Get type configuration for webtop application (tabs and position)
select distinct r_object_id, display_config, i_is_replica, i_vstamp, parent_id, scope_class, scope_value from dm_scope_config where r_object_id in (select distinct scope_config from dmi_dd_type_info where type_name='myType') and any scope_value = 'webtop'
Get the position and display mode of the attributes on all tabs
select r_object_id, attribute_display_hint, attribute_name, attribute_source, fixed_display, i_config_identifier, i_is_replica, i_vstamp, object_name from dm_display_config
where r_object_id in (select display_config from dm_scope_config where r_object_id in (select distinct scope_config from dmi_dd_type_info where type_name='type_name')
and any scope_value = 'webtop')
b) Modify display config for custom type
update dm_display_config objects
set attribute_source='custom_type'
set attribute_name[0]='r_object_id'
set attribute_display_hint[0]=1
set attribute_name[1]='attr_name'
set attribute_display_hint[1]=1
where r_object_id = '6bab413080033559'
c) Create a new display configuration (a new tab on properties page)
create dm_display_config object
set "object_name"='newTab'
set "attribute_source"='custom_type'
set "fixed_display"=0
append attribute_name='attr_name'
append attribute_display_hint=1
d) Add the new display config to the application (desktop, webtop, etc.)
UPDATE dm_scope_config OBJECTS
INSERT "display_config"[0] = (select r_object_id from dm_display_config where attribute_source='myType' and object_name='newTab') WHERE r_object_id in (select distinct scope_config from dmi_dd_type_info where type_name='custom_type') and any scope_value='webtop'
e) Remove a display configuration
UPDATE dm_scope_config OBJECTS
REMOVE "display_config"[index]
WHERE r_object_id in (select distinct scope_config from dmi_dd_type_info where type_name='myType') and any scope_value='webtop'
*The index must be known
Security tab
Set default ACL
ALTER TYPE type_name SET DEFAULT ACL acl_name [IN acl_domain]
ALTER TYPE type_name SET DEFAULT ACL NULL
Constraints tab
ALTER TYPE type_name [FOR POLICY policy_id STATE state_name] ADD constraint_specification
a) Primary Key
ALTER TYPE type_name
add PRIMARY KEY ("notnullAttr1")
REPORT 'TEXT'
ENFORCE BY APPLICATION
publish;
ALTER TYPE type_name
drop PRIMARY KEY
publish;
b) Unique Key
ALTER TYPE type_name
ADD UNIQUE ("notnullAttr4")
REPORT 'TEXT'
ENFORCE BY APPLICATION
publish;
ALTER TYPE type_name
DROP UNIQUE ("notnullAttr4")
publish;
c) Foreign Key
ALTER TYPE type_name1
ADD FOREIGN KEY("notnullAttr4") REFERENCES type_name2 ("pk2")
REPORT 'TEXT'
ENFORCE BY APPLICATION
publish;
ALTER TYPE type_name1
DROP FOREIGN KEY("notnullAttr4") REFERENCES type_name2 ("pk2")
publish;
Events tab
Add application events:
ALTER TYPE type_name
APPEND auditable_appevents = 'dm_ev0',
APPEND auditable_appevents = 'dm_ev1'
publish;
Add system events:
ALTER TYPE type_name
APPEND auditable_sysevents = 'dm_sysev0',
APPEND auditable_sysevents = 'dm_sysev1'
publish;

III. Modify custom type attributes settings
General tab
alter type typeName
modify (“rg_contry” (
set label_text='Country Name:',
set help_text = 'The name of the country' ,
set comment_text = 'comment',
set ignore_immutable = TRUE,
set is_hidden = TRUE,
set is_required = TRUE,
set not_null = TRUE,
set not_null_msg = 'L’attributo deve essere valorizzato',
set read_only = TRUE,
DEFAULT='DEFAULT VALUE'
))
Advanced tab
alter type typeName
modify “rg_contry” (
set is_searchable = TRUE,
append allowed_search_ops = 1,
append allowed_search_ops = 2,
append allowed_search_ops = 3,
set format_pattern = 'pattern',
set format_pattern_tag = 1,
set category_name = 'categorie',
set default_search_arg = 'somevalue',
set default_search_op = 3
)
Constraints tab
alter type type_name
modify “rg_contry” (
set ignore_constraints = TRUE,
set val_constraint='expression',
set val_constraint_dep = '????',
set val_constraint_enf = '????',
set val_constraint_msg = 'Error message for constraint violation'
)
ALTER TYPE type_name
MODIFY "pk" (
ADD PRIMARY KEY | UNIQUE KEY | NOT NULL
REPORT 'error message' on violation
ENFORCE BY APPLICATION
)
ALTER TYPE type_name
MODIFY "pk" (
DROP PRIMARY KEY
)
publish;
ALTER TYPE type_name1
MODIFY "pk" (ADD FOREIGN KEY REFERENCES type_name2("pk2")
REPORT 'message_string' ON VIOLATION ENFORCE BY APPLICATION)
ALTER TYPE type_name1
MODIFY "pk" (DROP FOREIGN KEY REFERENCES type_name2("pk2"))

Value Assistance tab
a) Set query
ALTER TYPE type_name
MODIFY “rg_country” (
VALUE ASSISTANCE IS QRY 'select distinct attribute_name from type_name order by 1'
qry attr = attribute_name allow caching is complete)
b) Set list
ALTER TYPE type_name
modify "countrycode" (VALUE ASSISTANCE is LIST ('ONE', 'TWO', 'THREE') IS COMPLETE)
c) Drop
ALTER TYPE type_name MODIFY "countrycode" (DROP VALUE ASSISTANCE)

Value Mapping tab
Add mapping
ALTER TYPE type_name
MODIFY "countrycode" (
MAPPING TABLE (
VALUE='UK'
DISPLAY='United Kingdom'
COMMENT='comment1',
VALUE='US'
DISPLAY='United States'
COMMENT='comment2'
))
publish;
Drop mapping
ALTER TYPE type_name MODIFY "countrycode" (DROP MAPPING TABLE)