Documentum Search 20.4 Docker install guide

Opentext has released with the 20.4 release a new search engine that will replace xPlore, and that currently is supported in “testing” mode.

Documentation for Documentum Search is better than previous documentations (parameters are finally “properly” explained), and you can also find a full .yaml file to use as template. However, as we could have expected, that didn’t work, so some changes are required.


Windows 10 x64 8GB RAM
VMware Workstation Player 15

CentOS 7.7 x64 25GB HD 4GB RAM 2 cores
PostgreSQL 11
Documentum 20.4

VM Creation

Just follow the Documentum 20.4 PostgreSQL post as I’ve used that VM.

Install Docker

Refer to Documentum 20.2 Docker install guide if you need help

Documentum Search 20.4

  • Get the images from the Opentext registry:

[dmadmin@dctm204 opt]$ docker login
[dmadmin@dctm204 opt]$ docker pull
[dmadmin@dctm204 opt]$ docker pull
[dmadmin@dctm204 opt]$ docker pull
[dmadmin@dctm204 opt]$ docker pull
[dmadmin@dctm204 opt]$ docker pull

  • Create folder structure. This is the one I’ve used:

[dmadmin@dctm204 opt]$ tree search
|– admin
| `– logs
|– agent
| `– logs
|– cps
| `– logs
|– cps2
| `– logs
|– lunr
| `– logs
|– search.yaml
|– solr
| |– base
| | |– log4j2.xml
| | `– logs
| |– logs
|– solr2
| |– base
| | |– log4j2.xml
| | `– logs
| |– logs
|– zoo
| |– data
| |– datalog
| `– logs
`– zoo.cfg

  • Create configuration files:

[dmadmin@dctm204 search]$ cp ../documentum/config/ .
[dmadmin@dctm204 search] vi zoo.cfg
[dmadmin@dctm204 search] vi solr/base/log4j2.xml
<extract this file from the solr container>

  • Create search.yaml:

[dmadmin@dctm204 search]$ sudo vi search.yaml
<copy the template from the documentation>

At this point, I had several issues with the solr image. First, the container could not write into the mounted folder. In order to fix this, I had to force the uid in the yaml file by adding the following:

user: ‘1000:1000’

After this, Java could not allocate memory for large memory pages. In the end I create a custom image based on the the one from OT (follow the steps detailed on the Reducing Opentext Documentum 20.2 Docker image size post:

[dmadmin@dctm204 search]$ docker run -u 0 –privileged -it –entrypoint /bin/bash
echo 22960 &gt; /proc/sys/vm/nr_hugepages
echo 1000 &gt; /proc/sys/vm/hugetlb_shm_group
echo “* soft memlock 626688” &gt;&gt; /etc/security/limits.conf
echo “* hard memlock 626688” &gt;&gt; /etc/security/limits.conf

  • Now if you’ve adjusted the values correctly on the yaml file (stick to 2 “replicas” or the container will also fail) you should be able to run

[dmadmin@dctm204 search]$ docker-compose -f search.yaml up

After a while, you should be able to login into the Documentum Search admin page (http://your-host:8800/):

search_consoleAnd if you log in Documentum Administrator:


However, if you run a search, you’ll see that there’s an error and the search is not perfomed. If you watched the Opentext World breakout session for Documentum Search, you’ll probably notice the extra settings used on server.ini to configure the fulltext engine. I’ve tried those without luck, so I just took another approach, to $DOCUMENTUM/product/20.4/bin and do the following:

[dmadmin@dctm204 bin]$ mv libDsearchQueryPlugin.bak
[dmadmin@dctm204 bin]$ cp

UPDATE: The “nice way” is doing this by editing the dmfulltext.ini file located in $DOCUMENTUM/fulltext.

Then restart the repository and searches should be working on the new search engine:

CMIS REST interface slow performance with multiple repositories

When using the REST interface provided by CMIS, if you have multiple repositories on your docbroker, you may have noticed a slight delay in the response to your queries. I came across this issue in an environment with multiple repositories (+10), where additionally, every dmadmin user has different password, so not only we had this delay on the responses, we also had a log full of authentication errors.

If the delay was slighty concerning, the errors thrown on the log pointed to something more serious (and most likely a known issue in D2).

With a little bit of debugging and decompiling, we found out the culprit on opencmis-dctm-connector-XXX.jar, in the com.emc.documentum.fs.cmis.impl.cmisoperations.impl.GetRepositoryInfosOperationHandler class. This (surprise surprise) is the same situation that we saw with D2. Check the getRepositoryInfoList method:

private List getRepositoryInfoList(CallContext context, GetRepositoryInfosOperationInputBean inputBean, List repositoryEntries)
     List repositoryInfoList = new ArrayList();
     for (CmisRepositoryEntryType repositoryEntry : repositoryEntries)
       String repositoryId = repositoryEntry.getRepositoryId();
       if (CmisAuthenticationManager.INSTANCE.authenticate(context, repositoryId)) {
         repositoryInfoList.add(getRepositoryInfo(context, inputBean, repositoryEntry));
     return repositoryInfoList;

Yes, they’ve done it again. The code tries to authenticate with the provided credentials in evey single repository known to the docbroker. Luckily for us, this method has the requested repository (i.e.: http//cmis…/resources/RepositoryName/…) in the context variable, so you can just do a comparison there and “magically” improve the perfomance (or wait until Opentext releases a “fix”).

Note that this happens in every version I could test from 16.4 to 20.4 😦

Opentext Documentum 20.4 PostgreSQL Install Guide

This is a step-by-step guide to install Documentum 20.4 in a Linux environment with PostgreSQL 11.


Windows 10 x64 8GB RAM
VMware Workstation Player 15

CentOS 7.7 x64 25GB HD 4GB RAM 2 cores
PostgreSQL 11
Documentum 20.4

VM Creation

Mount the CentOS 7 DVD image, boot the machine and follow the steps. You can choose to let EasyInstall do the work for you. I used minimal package install to save resources, named the machine dctm204, configured the network and set the root password as well as a “dmadmin” user.

OS Configuration

  • Install required packages:

[dmadmin@dctm204 ~]$ sudo yum -y install bash-completion kernel-devel rng-tools.x86_64 policycoreutils policycoreutils-python selinux-policy selinux-policy-targeted libselinux-utils setroubleshoot-server setools setools-console mcstrans expect tcl
[dmadmin@dctm204 ~]$ sudo yum -y group install X Window System “Development Tools”
[dmadmin@dctm204 ~]$ sudo yum -y install open-vm-tools.x86_64

  • Stop and disable the firewalld service:

[dmadmin@dctm204 ~]$ sudo systemctl disable firewalld
Removed symlink /etc/systemd/system/
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[dmadmin@dctm204 ~]$ sudo systemctl stop firewalld

  • Configure entropy and allow http connections through selinux:

[dmadmin@dctm204 ~]$ sudo /sbin/rngd -b -r /dev/urandom -p /dev/random
[dmadmin@dctm204 ~]$ sudo setsebool -P httpd_can_network_connect_db 1
[dmadmin@dctm204 ~]$ sudo chkconfig rngd on

PostgreSQL Configuration

  • Install required packages:

[dmadmin@dctm204 ~]$ sudo yum -y install
[dmadmin@dctm204 ~]$ sudo yum -y install postgresql11 postgresql11-server

  • Init the DB:

[dmadmin@dctm204 ~]$ sudo /usr/pgsql-11/bin/postgresql-11-setup initdb

  • Enable and start the PostgreSQL service:

[dmadmin@dctm204 ~]$ sudo systemctl enable postgresql-11
Created symlink from /etc/systemd/system/ to /usr/lib/systemd/system/postgresql-11.service.
[dmadmin@dctm204 ~]$ sudo systemctl start postgresql-11

  • Configure the postgres user:

[dmadmin@dctm204 ~]$ sudo passwd postgres
Changing password for user postgres.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.

[dmadmin@dctm204 ~]$ su – postgres
-bash-4.2$ psql
psql (11.5)
Type β€œhelp” for help.

postgres=# password postgres
Enter new password:
Enter it again:
postgres=# q
-bash-4.2$ exit

  • Configure PostgreSQL:

[root@dctm204 ~]# vi /var/lib/pgsql/11/data/postgresql.conf
listen_addresses = β€˜*’
port = 5432

[root@dctm204 ~]# vi /var/lib/pgsql/11/data/pg_hba.conf
host all all md5
host all all ::/128 md5
host all all dctm204 md5

  • Restart PostgreSQL service to apply the changes:

[dmadmin@dctm204 ~]$ sudo systemctl restart postgresql-11

phpPgAdmin Configuration

  • Install required packages:

[dmadmin@dctm204 ~]$ sudo yum install -y php php-cli php-common php-pdo php-pgsql httpd apr apr-util httpd-tools libzip mailcap
[dmadmin@dctm204 ~]$ wget
[dmadmin@dctm204 ~]$ tar -zxvf REL_5-6-0.tar.gz
[dmadmin@dctm204 ~]$ mv phppgadmin-REL_5-6-0/ /usr/share/phppgadmin
[dmadmin@dctm204 ~]$ mv /usr/share/phppgadmin/conf/ /usr/share/phppgadmin/conf/

  • Configure phpPgAdmin:

[dmadmin@dctm204 ~]$ sudo vi /etc/httpd/conf.d/phpPgAdmin.conf

Alias /phppgadmin /usr/share/phppgadmin

<Location /phppgadmin>
<IfModule mod_authz_core.c>
# Apache 2.4
Require all granted
#Require host
<IfModule !mod_authz_core.c>
# Apache 2.2
Order deny,allow
Allow from all
Allow from
Allow from ::1
# Allow from

[dmadmin@dctm204 ~]$ sudo vi /etc/phpPgAdmin/

$conf[β€˜servers’][0][β€˜host’] = β€˜dctm204’;
$conf[β€˜extra_login_security’] = false;
$conf[β€˜owned_only’] = true;

[dmadmin@dctm204 ~]$ sudo cp /etc/phpPgAdmin/ /etc/phpPgAdmin/

  • Restart httpd service to apply the changes:

[dmadmin@dctm204 ~]$ sudo systemctl restart httpd

Now you should be able to login to the console from http://dctm202/phppgadmin/.

ODBC Configuration

  • Install required packages:

[dmadmin@dctm204 ~]$ sudo yum -y install postgresql11-odbc.x86_64 unixODBC.x86_64

  • Configure .ini files:

[dmadmin@dctm204 ~]$ sudo vi /etc/odbcinst.ini
Description = ODBC for PostgreSQL
#Driver = /usr/lib/
#Setup = /usr/lib/
#Driver64 = /usr/lib64/
#Setup64 = /usr/lib64/
Driver = /usr/pgsql-11/lib/
Driver64 = /usr/pgsql-11/lib/
Setup64 = /usr/lib64/
FileUsage = 1
[dmadmin@dctm204 ~]$ sudo vi /etc/odbc.ini

  • Test the connection:

[dmadmin@dctm204 ~]$ isql -v MyPostgres
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
SQL> quit

Documentum server

  • Create folders:

[dmadmin@dctm204 ~]$ sudo mkdir -p /opt/documentum && sudo chown dmadmin.dmadmin /opt/documentum && mkdir /opt/documentum/product && mkdir /opt/documentum/product/20.4 && mkdir -p /opt/documentum/sw/cs

  • Install openJDK 11.0.7 (remember to remove “anon” from the list of disabled algorithms or the installer will fail to connect to the repository)

[dmadmin@dctm204 cs]$ wget
[dmadmin@dctm204 cs]$ tar xvf OpenJDK11U-jdk_x64_linux_11.0.7_10.tar.gz && mv openjdk-11.0.7+10/ /opt/documentum/

  • Set up environment variables:

[dmadmin@dctm204 ~]$ vi ~/.bash_profile

export DM_HOME


export JAVA_HOME

export PATH

export LC_ALL


  • Reserve ports for services:

[dmadmin@dctm204 ~]$ sudo vi /etc/services
dctm204 50000/tcp # dctm 20.4 repo
dctm204_s 50001/tcp # dctm 20.4 repo

  • Create symbolic link for later (configuration program):

[dmadmin@dctm204 ~]$ sudo ln -s /usr/lib64/ /usr/lib64/

  • Configure limits.conf:

[dmadmin@dctm204 ~]$ sudo vi /etc/security/limits.conf
dmadmin – core -1

  • Run the installer:

[dmadmin@dctm204 cs]$ tar -xvf content_server_20.4_linux64_postgres.tar
[dmadmin@dctm204 cs]$ chmod 777 serverSetup.bin
[dmadmin@dctm204 cs]$ ./serverSetup.bin

Docbroker and repository

  • Create the tablespace file for the repository (dctm202):

[dmadmin@dctm204 cs]$ su –
[root@dctm204 ~]# su – postgres
-bash-4.2$ mkdir /var/lib/pgsql/11/data/db_dctm204_dat.dat
-bash-4.2$ exit
[root@dctm204 ~]# exit

  • Run the configurator:

[dmadmin@dctm204 install]$ ./

And you should know the rest πŸ™‚

Java 11 Documentum REST Client examples

On Java 11, HttpClient was added to Java (no more need to use Apache’s HttpClient). and this presents some changes to the usual way of consuming Documentum REST services. The main “issue” is that there is no MultiPart class provided to easily handle multipart content (create a document), so we need to do it manually. I’ve upload a project to GitHub with basic examples of using Documentum REST services with Java 11: DctmRest11

D2 slow loading login screen

You may have realized that D2 takes some time to load the login screen when you want to log in. The usual behaviour is that after typing D2’s url in your browser, you’ll see something that looks like a loading screen (after d2 spin wheel):

and after a few moments the login screen in shown.

This behaviour is not something Documentum users are used to when using Webtop so, why this happens? Well, by now you’ve probably realized that D2 does not show the repository name, but the repository description. And in a questionable design decision, this processing is done every time the login screen is loaded (=every time a user access).

This happens on C6-Common\com\emc\common\dctm\objects\DfDocbaseMapEx class and the effect is quite clear as it is shown in this log trace:

c.e.c.d.o.DfDocbaseMapEx[] : Load docbases from docbrocker 8.925s

Yes, here we have users waiting for 9 seconds before the login screen is shown, and this happens every single time they try to access D2.

So, what wizardry is behind this odd behaviour? Let’s check it:

public DfDocbaseMapEx(String attrName, String direction) throws DfException {
    StopWatch stopWatch = new StopWatch(true);
    this.m_docbases = new TreeSet(new DfDocbaseComparator(this, attrName, direction));
    IDfClient client = DfClient.getLocalClient();
    IDfDocbaseMap docbaseMap = client.getDocbaseMap();

    int count = docbaseMap.getDocbaseCount();
    for (int i = 0; i < count; i++) {
      try {
        String server;
        IDfTypedObject serverMap = docbaseMap.getServerMap(i);
        String name = docbaseMap.getDocbaseName(i);
        String currentServer = serverMap.getString("i_host_name");

        if (serverMap.findString("r_host_name", currentServer) == -1) {
          server = serverMap.getRepeatingString("r_host_name", 0);
        } else {
          server = currentServer;
        String description = docbaseMap.getDocbaseDescription(i);
        String version = docbaseMap.getServerVersion(i);
        DfDocbaseEx docbase = new DfDocbaseEx(this, name, server, description, version);
      catch (DfException e) {
        LOG.error("{}", e);
    LOG.debug("Load docbases from docbrocker {}", stopWatch);

Well, there is no much mistery here, getting an IDfTypedObject for each repository registered in your docbroker, every single time a user logs in… it may not be very noticeable with one repository, but try this code with +10 repositories… You can add logging inside the loop and check how much time takes for each repository…

This questionable design decision, makes you also wonder about other behaviors/configurations from D2:

  • Repository filter option: This acts as a simple cosmetic filter, as you can see that there’s no filtering when the list is populated. This means that you can have one repository listed, but you still have to wait for all the repositories to be “processed”
  • If you have enabled autologin/default repository, you’ll face the same situation, users will be logged in directly… after several seconds waiting for the login screen (that they won’t see) to finish loading.

So, what can we do to fix it (besides waiting for OT to fix it)?. Well, as you can see the code is no rocket science, so there are a bunch of possibilities:

  1. Don’t process every single time the repository list (basically check if this.m_docbases == null or size == 0)
  2. Load and actually apply the repository filter inside the for loop
  3. Process autologin setting as in #2
  4. Add an option in D2FS/ to use repository name and forget about description
  5.  Don’t instantiate the servermap and use i_host_name from docbaseMap

By implementing any of these approaches you’ll get something like this when loading the repository list:

Standard D2:
repo1:16.4.0100.0153 Linux64.Oracle -> 1.087s
repo2:16.4.0100.0153 Linux64.Oracle -> 1.093s
repo3:16.4.0100.0153 Linux64.Oracle -> 1.098s
repo4:16.4.0100.0153 Linux64.Oracle -> 1.108s
Total: 4.389s
Modified D2:
repo1:16.4.0100.0153 Linux64.Oracle -> 0.000s
repo2:16.4.0100.0153 Linux64.Oracle -> 0.000s
repo3:16.4.0100.0153 Linux64.Oracle -> 0.000s
repo4:16.4.0100.0153 Linux64.Oracle -> 0.000s
Total: 0.002s

And users will be much happier than before πŸ˜€

dqMan configuration with Documentum 16.4 or newer

As it seems that people are still struggling with configuring fme group‘s dqMan after dmcl support was removed in Documentum 16.4, maybe this will be helpul. I’m doing this with Documentum 20.2, but this works for every other version.

Let’s start

  1. Install Java:
    • You will need x86 Java, x64 won’t work
    • If you’re using any Java newer than 1.8.201, you need to enable the anon cipher for the secure mode to work
      • Oracle JRE: jre\lib\security\ file, you need to remove anon from jdk.tls.disabledAlgorithms entry
      • OpenJDK: opendk\conf\security\, you need to remove anon from jdk.tls.disabledAlgorithms entry
  2. Install DFC
    • You need to install DFC using the x86 Java, otherwise dqman won’t work. You can check which Java is DFC using in Windows registry (HKEY_LOCAL_MACHINE\SOFTWARE\Documentum\java).
  3. Install dqman
  4. Copy dmcl.dll from a previous Documentum version to dqman’s folder. Be aware that there’s actually two different dcml.dll version (I think one is 32bit and another 64bit). As far as I know, the one that works is the smaller one (~150KB)

That’s it πŸ™‚

If you come from previous versions of dqman, remove any dmcl40.dll / dmcl.ini from dqman’s folder or the PATH/CLASSPATH entries.

Usual Error:


This means you are running dqman with x64 Java (which does not work)

If you have multiple Java’s installed, you can force dqman to use a specific one by creating a java.ini file in dqman’s folder including the following:

java_library_path=”c:\java18\bin\client\jvm.dll” -> path to jre’s jvm.dll
#java_classpath = “dfc\lib\dctm.jar;dfc\config” -> this entry is optional (commented with #). If defined, it has to include the folder containing dctm.jar file and a folder with file

If you did everything correctly you should see the following on the about window:


Improving Opentext’s Documentum Administrator 20.2 Docker container

If you go looking for Documentum’s DA 20.2 Docker file you’ll find the following:

documentum_adminstrator_20.2_docker_centos.tar (1.4 GB)

What’s wrong with this? Well, in a container world (specially when using application servers) why is there the word “centos” and why a tomcat is 1.4 GB?

The answer is simple: Whoever built this image didn’t know what a container is, and it seems that nobody knows yet at Opentext.

What is a container? Well you can google it, but a container IS NOT A VM, it is a process. The idea behind containers is to have an isolated process that can be easily scalable (ie: deploy multiple similar tomcat instances quickly). So what’s the point of running a Docker environment when what we are doing is simply deploying VM’s? None at all.

So let’s assume we can use an actual container, that can be scaled up quickly, and won’t force us to “redeploy” a Centos OS on each container (for Tomcat, as DA is not a process and should not be “a container”), what should we do? Here we go (Note that I’ve used the same VM used for Opentext Documentum 20.2 Docker with PostgreSQL install guide):

  • Pull Tomcat 9 + openJDK 11 image from DockerHub:
[dmadmin@dctm202 ~]$ docker pull tomcat:9-jdk11
9-jdk11: Pulling from library/tomcat
f15005b0235f: Pull complete
41ebfd3d2fd0: Pull complete
b998346ba308: Pull complete
f01ec562c947: Pull complete
74c11ae3efe8: Pull complete
c65829cc6c71: Pull complete
b98eacc09bf1: Pull complete
b12b9c976670: Pull complete
62a47f54db4c: Pull complete
8c872760f50c: Pull complete
Digest: sha256:2254679f4958efe7c9810d6a66d449f58b58-p 8888:80808ecd253e83e9d3afb68c51637cf4
Status: Downloaded newer image for tomcat:9-jdk11

[dmadmin@dctm202 ~]$ docker images
tomcat 9-jdk11 54877c1fa80a 40 hours ago 647MB
  • Create the following folder structure and copy there these files:
/opt/docker/tomcat/conf/web.xml (just for Tag Pooling)
/opt/docker/tomcat/webapps/da.war (Da to deploy)
/opt/docker/tomcat/ (with anon whitelisted)
  • Run container (I’ve used 8888 as external port as the VM has another Tomcat running on 8080):
[dmadmin@dctm202 tomcat]$ docker run -it --rm -p 8888:8080 --name tomcatda -v /opt/docker/tomcat/ -v /opt/docker/tomcat/conf/web.xml:/usr/local/tomcat/conf/web.xml -v /opt/docker/tomcat/webapps:/usr/local/tomcat/webapps tomcat:9-jdk11

And that’s it, you now have a 650MB real container for DA.

Reducing Opentext Documentum 20.2 Docker image size

The Docker image size provided by Opentext for the Content Server is a ~3.5GB tar file:

[dmadmin@dctm202 ~]$ docker images
contentserver/centos/stateless/cs 20.2.0000.0110 f83cfb099daf 3 weeks ago 3.48GB

But if you run the image, you’ll see that the actual size of the container is ~2.6GB.

This difference comes from the intermediate layers stored on the original image. If you want to have a smaller image, you could export the container to a .tar file, but if you do this, you will lose all the default configurations required for running the container (ports exposed, entry point, etc.). But there’s a workaround to get a working trimmed image:

docker run -it --entrypoint /bin/bash contentserver/centos/stateless/cs:20.2.0000.0110
  • You can be as “aggressive” as you want removing unused stuff. You can skip this point, but I would at least delete all .dll files and aix/hpux/sol/win folders from com.emc.ide.external.dfc_1.0.0/dmbasic on Composer’s plugin folder, as those don’t make sense on a Linux image.
  • Run the docker rebase script:
./docker-rebase <CONTAINER_ID> contentserver/centos/stateless/cs:20.2.4
  • Export the generated image:
docker save contentserver/centos/stateless/cs:20.2.4 > cs202clean.tar

Now, you’ll have the following:

[dmadmin@dctm202 Scripts]$ docker images
contentserver/centos/stateless/cs 20.2.4 5336da9204b0 34 minutes ago 2.49GB