Remote DAR install

A usual challenge when trying to automate Documentum operations is how to streamline the installation of dar files. These are done via a huge application (composer, basically a customized eclipse) that teams usually mount into some container / server to run these intalls.

However, there’s a simpler way to get this to work: by using a REST endpoint.

1. Create a method to run the dar intall from the content server by running a command line script:

java -Ddfc.keystore.file=$DOCUMENTUM/config/dfc.keystore -Ddar=$1.dar -Dlogpath=/tmp/darinstaller.log -Ddocbase=$2 -Duser=dmadmin -Ddomain= -Dpassword=dmadmin -cp $DM_HOME/install/composer/ComposerHeadless/startup.jar org.eclipse.core.launcher.Main -data $DM_HOME/install/composer/workspace -application org.eclipse.ant.core.antRunner -buildfile $DM_HOME/install/composer/deploy.xml

Note that this is an example where we’re willingly ignoring the user/password authentication as this will be delegated to the REST call.

2. Create a REST extention point to run this. This a simple example of the controller class:

public ContentfulObject createObject(@PathVariable("repositoryName") final String repositoryName,  @RequestBody final InstallDarInfo createObject,  @TypedParam final SingleParam param,  @RequestUri final UriInfo uriInfo)
        throws Exception {

    createObject.addAttribute(new Attribute("object_name",createObject.getDar()));
    createObject.setType("dm_document");

    ContentfulObject result = sysObjectManager.createSysObjectUnderParentFolder(createObject, "/Temp/installDAR", true, param.getAttributeView());

    Map<String, Object> params = Collections.singletonMap(ViewParams.POST_FROM_COLLECTION, (Object) true);  

    runInstallDARMethod(repositoryName, result.getId(), (String)result.getAttributeByName("object_name"),"/Temp/installDAR") ;
    return (ContentfulObject) getRenderedObject(repositoryName, (ContentfulObject)result, param.isLinks(), uriInfo, params);
}

private void runInstallDARMethod(String repository, String objectId, String fileName, String folderPath) throws DfException {

    String dqlMethod="execute do_method with method='m_InstallDAR', arguments='"+ objectId + " " + fileName + " " + repository + " " + folderPath + "', launch_async=true, run_as_server=true";
    this.queryEngine.execute(QueryResultItem.class, dqlMethod+";", QueryType.QUERY, 0, 100);
}

As you can see, this simply takes the file attached to the REST call, stores it on a temporary folder on the repository, and then calls the method to run this.

With this, you can also handle something that, if you’ve played with Documentum cloud images, you might have already realized that OT engineers do not know: The additional artifacts that come with DAR files (install parameters, locales, referenced dar files, etc. The usual stuff “nobody” uses in the real world). Also, you can process several files (ie: zip file containing everything needed to install), you can store the output log, return the log, use different build files depending on your needs, etc.

However, this still presents a challenge: you need to deploy this on DCTM-REST and create a method to run the script that needs to be placed on the CS.

So, is there anything else we can do? Yes 😀

From a couple versions back (20.x?) Documentum has included a JMS servlet to run DAR installs (InstallDarServlet). This is a rather “simple” class that basically receives a couple of parameters (repository, user, login ticket and an object_id from a dar file existing in the repository) and it will run a simple dar install. This servlets presents “great room for improvement”, so you can create a class with the same name and package, copy the code (so you don’t break whatever OT is using this for) and then add a handler for a multipart REST message which does everything we’ve discussed before and then replace this class on the CS. By doing this you will get:

  1. Simplest deployment for deploying DAR files automatically (just replacing one class and restarting JMS, as the servlet is already present on web.xml)
  2. You really don’t need to store anything on the repository, this can be run synchronously (be aware of long running DAR installations) and return the whole log, or you can store everything in the repository as audit trail.
  3. You can handle install parameters, locales, referenced dar files, etc. (which again, seems something that OT engineering have never heard of, who really uses locales? everyone loves systems on English :D)
  4. You can control the access to this servlet via user/password, by allowing only certaing IPs to call it and using trusted login to install DAR files, etc

Documentum REST dm_job object on DQL queries

If you have used dctm-rest 21.x, you might have come across this error when doing something like select * from dm_job:

E_INPUT_ILLEGAL_ARGUMENTS: There are illegal arguments provided. Failed to instantiate class class com.emc.documentum.rest.view.impl.QueryResultItemView with arguments..

You might wonder if you did something wrong when deploying dctm-rest or if there’s something missing on your environment. Well, the answer is no. If you change the DQL to something like:

select *,r_object_id as method_id from dm_job

Magic! It works 🙂

Well, the “issue” is on the com.emc.documentum.rest.view.impl.JobView class, where someone at some point decided that it was a good idea to require a non-existing attribute (method_id) in dm_job view class:

protected void addMethodsLink()
{
String methodId = (String)((JobObject)getDataInternal()).getMandatoryAttribute("method_id");
makeLinkIf(!methodId.equals("0000000000000000"), CoreLinkRelation.METHOD.rel(), idUriBuilder("method", methodId).build());
}

Also, if you want a more “permanent” solution you can override this method with something like:

protected void addMethodsLink()
{
String methodId = (String)((JobObject)getDataInternal()).getMandatoryAttribute("method_id");
if (methodId!=null){
makeLinkIf(!methodId.equals("0000000000000000"), CoreLinkRelation.METHOD.rel(), idUriBuilder("method", methodId).build());
}
}

And you’ll be good to go.

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 😦

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