cmis-in-batch & Documentum 6.7

I have just pushed changeset which enables Documentum 6.7 support in cmis-in-batch. Generally speaking OpenCMIS supports Documentum 6.7 out of the box, but cmis-in-batch required some additional modifications due to the way how Documentum handles paths to objects. Documentum allows multiple objects with the same name in a single folder and therefore it is impossible to uniquely address an object using a typical path. To solve this problem Documentum uses different path segments, each object name is represented in following form:

with name: 0900000b80001234_docname
without name: 0900000b80001234_

Other limitation of Documentum 6.7 CMIS is that it exposes only CMIS object types (document, folder and relationship) and not custom ones, therefore the fail-when-type function will not work as expected.

You can get the latest source code using Mercurial like this:

hg clone cmis-in-batch 


I have just uploaded an initial version of tool which tries to simplify data import and manipulation in CMIS enabled repositories.

More details as well as source code (under Apache License 2.0) are available here:

It is still Work In Progress but it works, at least now, with Alfresco. I have just finished installation of Documentum 6.7 with newly added CMIS support and I am going to test it as soon as possible.

Data importer for CMIS repositories

When developing Stamper I missed a tool which would allow me to easily import some files into a repository. Alfresco provides import/export functionality through ACP files which can be used for that purpose but what about other repositories? What about Nuxeo, Documentum? Documentum has Composer/Application Builder, Nuxeo perhaps also has it’s own mechanisms, but I wanted one tool which would work with all those repositories without need to create a separate installation package for each system.

Hopefully there is a CMIS standard which can make this happen.

CMISetuper (working name :-)) will be a tool which will be able to:

  • connect to any repository which supports CMIS. This will be possible thanks to the OpenCMIS library.
  • import files
  • create folders
  • validate presence of types, objects, folders
  • modify content (replace, version etc.)
  • link and unlink objects from folders

Those actions will be described by a declarative language named SDL – Simple Declarative Language. Below is a fragment of a script:

execute {
    import-files "/myFiles" {
        "image1.jpg" cm_name="Some title" metasys_taken_on_date=2009/10/05
        "image2.jpg" metasys_color=false metasys_taken_on_date=2011/01/05

    import-file "/Documents" "someotherfile.doc"
    delete-file "/Old document.doc" all-versions="true"

    replace-content "/Pictures/picture.jpg" "/tmp/newContent.jpg"
    update-properties "/Documents/someotherfile.doc" cm_title="another title"
    link-to-folder "/myHouse.jpg" "/myFiles"
    unlink-from-folder "myHouse.jpg" "/myFiles"

Basically the tool will execute scripts in a few stages:

  • pre-validate stage – this stage can check presence of types, files, folders etc. in repository and fail when they are present (or not).
  • prepare stage – at this stage some preparations can take place, for example creation of folders for which objects will be imported.
  • execute stage – this is the main stage which takes care of actual data importing, linking etc.
  • validation stage – the last stage which checks whether everything was imported correctly

Some global settings will be available which will control overwrite mode as well as whether to stop on errors.
I have also plan to implement rollback mode but perhaps not in the first version 🙂

At this moment I would say that around 60% of above functionality is implemented and I hope to have rest ready by end of this week, so stay tuned for updates!

If you have some new ideas please share them with me.

Disabling TBO (BOF v2) in Documentum 5.3+

Sometimes during development it is useful to disable a Typed Based Object (TBO). In Documentum 5.3 (and older) when Business Object Framework was at version 1 it was easy, all that has to be done was commenting out the TBO definition line in $DOCUMENTUM/config/ From now on the TBO will be disabled in that particular DFC instance.

In BOF version 2 things have complicated because is no longer used (or at least recommended), instead all BOF objects are defined in the repository as dmc_module object instances. There is an easy way to disable a TBO globally by renaming the dmc_module object in /System/Modules/TBO but it will disable that TBO for all users and sometimes when doing troubleshooting on, for example, production system it is desirable to disable TBO only on one client.

In order to disable TBO on a single client machine we have to do a trick. Each DFC instance has it’s own BOF cache, which usually is in $DOCUMENTUM/cache. We have to locate the dmc_jar implementing the TBO and replace it with a dummy one which will not contain any business logic. How to locate the right dmc_jar? Well, it requires some investigation, you can either use DQL to look for the r_object_id of dmc_jar or just check files in the cache folder and look for JAR which will contain class implementing given TBO.

Next step is to prepare a dummy TBO. Dummy TBO is in all cases almost the same, what changes is the name of the class and package name. Sometimes different TBO objects are implementing different interfaces (for example IDfDynamicInheritance is not a required one) so in worst case you can look it up in the sources (or decompile the original TBO JAR file) and see how it was declared.

Typical Java code is following:

package com.documentum.cvp.common;

import com.documentum.fc.client.DfDocument;
import com.documentum.fc.client.IDfBusinessObject;
import com.documentum.fc.common.DfException;
import com.documentum.fc.common.IDfDynamicInheritance;

public class CvpDocument extends DfDocument
    implements IDfBusinessObject, IDfDynamicInheritance

    public CvpDocument()

    public String getVersion()
        return "1.0";

    public String getVendorString()
        return "Documentum";

    public boolean isCompatible(String version)
        return version.compareTo("1.0") == 0;

    public boolean supportsFeature(String feature)
        return false;

When dealing with DfFolder just change DfDocument to DfFolder and it should be fine.

After compiling the Java class and replacing the old JAR in the cache client application has to be restarted. It is also worth mentioning that the cache is periodically refreshed so it is a good idea to check whether our dummy TBO implementation was not overwritten by the real one. From my experience I can say that it happens very rarely.

I have tested this approach and I can confirm that it works, it saved me a lot of troubles during data migration between systems using FirstDoc.