Share This Post

Why use the operations package?

I have a feeling many of you (like the author) have seen the Operations package in the
DFC, but quickly skip over it, not really understanding the advantages to its use.
While it is true you can use the core methods of the DFC to accomplish the same
task, the Operations package offer some unique advantages:

  • Same functionality with less coding
  • Less chance of introducing logic errors in an operation
  • If the logic of an operation ever changes, the DFC will reflect this change
    without having to change your code

By using the Operations provided in the DFC, you now have a standard framework
for processing your Documentum actions. And while you may deem the Operations package
as unnecessary for your simple objects, remember that the Operations also support
virtual documents, XML documents, compound documents, assemblies, related documents,
and deep folder contents. This is where the real power of using the operations framework
comes into play. A system that was once built to only handle simple objects, now
has the capability to handle something an order of magnitude more complex.

Basic Concepts

Operations are very intuitive. If you were to imagine a move operation you would
imagine that you would need to use an operation called “move”, then tell it what
object you needed to move, and where you wanted to move it to, and finally
execute the function and handle any errors that may have occured.

It turns out, this is exactly how Operations are handled in the DFC. These steps
are straight from the Documentum Reference:

  1. Create – the operation class
  2. Populate – with settings/parameters
  3. Execute – carry out the operation
  4. Handle Errors – read any exceptions
  5. Process Results – if your program needs the output of the operation


Let’s use our basic understanding of Operations to now actually use them. We’ll
go through each of the steps above, detailing how to do them programatically.

1. Create

The first step is to create an interface of the operation you wish to use.
The operations at your disposal all descend from xmlns:xsi=””>IDfOperation. Just
for reference, these are currently the operation interfaces available:

  • Import
  • Export
  • Checkout
  • Checkin
  • CancelCheckout
  • Copy
  • Delete
  • Move
  • Validation
  • Transform

Now, watch closefully, because what I am about to do here is not the way
Documentum says to create an instantiation of this Operation. In their examples,
they tell you to use the xmlns:xsi=””>getOperation() factory method to produce
an xmlns:xsi=””>IDfOperation. This method is in the xmlns:xsi=””>IDfClientX class,
and not visible to a java programmer. Therefore, you have to instantiate this
class with a new to the undocumented xmlns:xsi=””>DfMoveOperation class, like this:

DfMoveOperation moveOperation = null;
try {
moveOperation = new DfMoveOperation();
}catch(DfException excInstantiate) {
System.out.println("error instantiating the class: " + excInstantiate);

Note: If there is a better way to do this, or I am just wrong, please drop me an email.

2. Populate

The next step is to populate the operation with any settings that it may need.
We are using a very simple operation in this example, but in the case of a checkout
for a virtual document, this becomes slightly more work. To get back to our move
example, here is what the code looks like to populate the information the operation
needs to accomplish its task:

// string Ids for parameters
// fill the xxxxx, yyyyy, and zzzzzz with valid r_object_id in your docbase
String objectIdString = "xxxxxxxxx";
String srcFolderIdString = "yyyyyyyyy";
String destFolderIdString = "zzzzzzzzz";

// Ids for parameters
IDfId srcFolder = new DfId(srcFolderIdString);
IDfId destFolder = new DfId(destFolderIdString);
IDfId obj = new DfId(objectIdString);

// actual object to move
IDfSysObject sysObj = (IDfSysObject) session.getObject(obj);

// add object to operation
IDfOperationNode opNode = moveOperation.add(sysObj);

// set source and destination parameters

3. Execute

Now, everything is prepared, and you can actually execute the operation. Although
the execute commands can throw a DfException, it will only do this if there is a fatal
exception, as we will catch any other exceptions later. Each node that you have added
to the operation is now executed.

boolean retVal = moveOperation.execute();

4. Handle Errors

The execution step will do all it can not to throw an exception, and instead lets
you read from the xmlns:xsi=””>getErrors() method of xmlns:xsi=””>IDfOperation in
order to receive any information on problems during the execution. This method
will return an xmlns:xsi=””>IDfList which can then be traversed. The reason that
an exception is not thrown may not be immediately obvious in an example such as
this, but when dealing with multiple nodes that are added to an operation it makes
complete sense. For example, let’s say you were checking in 100 nodes with one operation.
Would you want a problem with node 59 to stop the entire batch? The operations package
lets you deal with this on an individual basis, and on certain operations will even
let you call the xmlns:xsi=””>abort() method if you really did want an all-or-nothing

If you just wanted to check if the move operation was successful, you could use
code like this:

System.out.println("The result of the operation was: " + retVal);

5. Process Results

When the operation is complete, there may be information that your program
would like to act upon, such as new IDs produced by the import operation that you
just executed. There are a couple of ways to get at this information, we will use
the “flat” list model, where there are no parent-child relationships to deal with.

Essentially, we will use the xmlns:xsi=””>getRootNodes() method of the xmlns:xsi=””>IDfOperation
class to iterate through the results. At each node, we will use the xmlns:xsi=””>getProperties()
method to get the list of property names, and pull each of the property values in the inner loop.
Here is some code that will show what object(s) were just moved in our example:

// get list of nodes operated on
IDfList rootNodes = moveOperation.getRootNodes();// get number of nodes in list
int count = rootNodes.getCount();
// go through each node and tell which operation was executed
for(int i=0;i<count;i++) {
// get specific node
IDfOperationNode node = (IDfOperationNode) rootNodes.get(i);
// get properties of node
IDfProperties props = node.getProperties();
// get list of names of properties
IDfList list = props.getProperties();
// go through each property and show value
System.out.println("The result of the " + node.getOperation().getName() + ":");
for(int j=0;j<list.getCount();j++) {
String propName = list.getString(j);
System.out.println(j + ") " + propName + " = " + props.get(propName) );
} // loop j
} // loop i


The Operations package of the DFC is an extremely valuable section of the DFC that
often gets overlooked by programmers. The fact that simple operations can be mimicked
by a few lines of core DFC methods, often make us falsely believe that they are not needed.
Nothing could be further from the truth. The use of the Operations package means that
the basic logic of your application will always work, even when the steps to carry it
out change as the objects you are manipulating become more complex. On top of this,
any performance tuning that DCTM does to the internal calls of that operation will
be released to your application as soon as you upgrade your DFC version.

More To Explore