Você está na página 1de 176

Developing DFC Applications

Version 5.1 March, 2003

Copyright 1994-2003 Documentum, Inc. 6801 Koll Center Parkway All rights reserved. Printed in USA.

Pleasanton, CA 94566

DOCUMENTUM, NOW YOU KNOW, UNITING THE WORLD THROUGH CONTENT, GMPHARMA, GXPHARMA, GDPHARMA, GSPHARMA and the Documentum corporate logo are trademarks or registered trademarks of Documentum, Inc. in the United States and throughout the world. All other company and product names are used for identification purposes only and may be trademarks of their respective owners.

Table of Contents

Preface ......................................................................................................................... Chapter 1 Getting Started With DFC .............................................................. Organization of the Manual ............................................................................. What is DFC? .............................................................................................. Where is DFC? ............................................................................................. Programming with DFC ................................................................................. Interfaces ................................................................................................ Client/Server Model .................................................................................. IDfPersistentObject ................................................................................... Processing a Docbase Object ....................................................................... Using DFC From Application Programs ............................................................ Java........................................................................................................ Visual Basic ............................................................................................. C++........................................................................................................ Syntax Differences .................................................................................... Creating DFC Client Objects ........................................................................... Java Example ........................................................................................... Visual Basic Example ................................................................................ Using DFC Tracing ....................................................................................... Packages ..................................................................................................... Using the DFC Online Reference Documentation ................................................ Working With Documents .............................................................. Introduction to Documents.............................................................................. Virtual Documents .................................................................................... XML Documents ...................................................................................... Introduction to Operations .............................................................................. Types of Operations....................................................................................... Basic Steps for Manipulating Documents........................................................... Steps for Manipulating Documents ............................................................... Details of Manipulating Documents .............................................................. Operations for Manipulating Documents ........................................................... Importing ................................................................................................ Exporting ................................................................................................ Checking Out ........................................................................................... Checking In ............................................................................................. Cancelling Checkout ................................................................................. Copying .................................................................................................. Moving ................................................................................................... Deleting .................................................................................................. Validating an XML Document Against a DTD or Schema ................................. Performing an XSL Transformation of an XML Document ...............................

9 11 11 12 13 13 13 14 14 14 15 16 16 16 17 17 17 18 18 18 20 21 21 21 23 23 24 24 24 26 28 28 30 31 32 34 34 36 36 38 39

Chapter 2

Developing DFC Applications

Table of Contents

Handling Document Manipulation Errors .......................................................... The add Method Cannot Create a Node ......................................................... The execute Method Encounters Errors ......................................................... Operations and Transactions ...........................................................................

41 41 41 45 47 47 47 48 48 49 49 50 50 51 52 55 55 55 56 56 57 57 57 58 58 61 61 61 62 62 62 63 63 64 64 65 65 65 66 66 66 67 67 67 68 69 69 69 71 72

Chapter 3

Working With Docbase Sessions ................................................ Introduction ................................................................................................. Managed and Unmanaged Sessions .............................................................. Session Manager ....................................................................................... Session Pool ............................................................................................ Using a Session Manager................................................................................ Lifetimes of Sessions and Managers ............................................................. Multiple Docbases .................................................................................... AuthenticationSetting and Managing Identities ................................................ Using Manual Identities ............................................................................. Using Principal Identities ........................................................................... Managing Docbase Queries with DFC ....................................... Queries ....................................................................................................... Flow of Query Processing ........................................................................... IDfQuery................................................................................................. IDfCollection ........................................................................................... Basic Query Examples ................................................................................... execQuery in Visual Basic .......................................................................... displayResults in Visual Basic ..................................................................... execQuery in Java ..................................................................................... displayResults in Java ................................................................................ ........................................................... Checking Objects Against Validation Rules........................................................ validate in Java ......................................................................................... Changing Permissions.................................................................................... changeBasicPermissions in Visual Basic........................................................ changeExtendedPermissions in Visual Basic .................................................. changeBasicPermissions in Java .................................................................. changeExtendedPermissions in Java ............................................................. Using Private ACLs ...................................................................................... privateACLs in Visual Basic ....................................................................... privateACLs in Java .................................................................................. ACL Utility Methods ..................................................................................... permissionToString in Visual Basic .............................................................. extendedPermissionToString in Visual Basic .................................................. displayBasicPermissions in Visual Basic ....................................................... displayExtendedPermissions in Visual Basic .................................................. permissionToString in Java ......................................................................... extendedPermissionToString in Java ............................................................. displayBasicPermissions in Java .................................................................. displayExtendedPermissions in Java ............................................................. Understanding Business Objects ............................................... Introduction to Business Objects ...................................................................... Overview of BOF ..................................................................................... Benefits of Using BOF ............................................................................... BOF Architecture ..................................................................................... Using Validation and ACLs

Chapter 4

Chapter 5

Chapter 6

Developing DFC Applications

Table of Contents

Service Based Business Objects ....................................................................... Architecture ............................................................................................. Rules and Guidelines ................................................................................. Type Based Business Objects .......................................................................... Introduction ............................................................................................. Architecture ............................................................................................. Implementation Rules, Guidelines, and Examples ........................................... Calling Rules, Guidelines, and Examples ....................................................... Error Handling ......................................................................................... Best Practices ........................................................................................... Documentum Business Object Registry (DBOR)................................................. Overview of DBOR .................................................................................. Architecture of DBOR ............................................................................... Using DBOR at Runtime ............................................................................ Managing DBOR ...................................................................................... Handling DBOR Errors ..............................................................................

77 78 79 83 83 83 85 88 88 88 89 89 90 91 91 93 95 95 96 96 96 97 97 99 99 105 106 108 112 112 112 113 115 116 119 121 121 121 121 128 131 132 132 132 134 135 136 136 137 137 138 138

Chapter 7

Developing Business Objects ...................................................... Getting Started with BOF ............................................................................... Overview of the Sample Business Objects ......................................................... The Simple_TBO Example ......................................................................... The Simple_SBO Example ......................................................................... A Simple TBO Example ................................................................................. Introduction ............................................................................................. Creating the IAutoNumberType Interface ...................................................... Creating the AutoNumberType Class ............................................................ Creating the com_accelera_autonumber Docbase Type ................................... Registering the TBO with DBOR ............................................................... Testing the TBO ..................................................................................... A Simple SBO Example ............................................................................... Introduction ........................................................................................... Defining the IAutoNumber Interface........................................................... Defining the AutoNumber Class ................................................................ Deploying and Registering the Service ........................................................ Implementing the Simple_SBO Test program ............................................... Running the Simple_SBO Test Program ...................................................... Using and Deploying Business Objects .................................. Using Business Objects ................................................................................ Overview .............................................................................................. Managing Sessions for Business Objects ..................................................... How to use a Business Object from WDK ................................................... How to use a Business Object from Visual Basic using IDispatch ..................... Deploying Business Objects .......................................................................... Overview .............................................................................................. Packaging .............................................................................................. Business Object Registration ..................................................................... Documentation ....................................................................................... Custom Installer/Uninstaller ...................................................................... AutoNumber Components ........................................................................ Overview of the DFC Interface Hierarchy ................................ Documentum Object Hierarchy ..................................................................... Subtypes and Supertypes .......................................................................... Persistence.............................................................................................

Chapter 8

Chapter 9

Developing DFC Applications

Table of Contents

Typed Objects ............................................................................................ Session and Identifier .............................................................................. Getting and Setting Attribute Values ........................................................... Additional Methods for Operating on Repeating Attributes ............................. Attribute Information ............................................................................... Persistent Objects........................................................................................ Methods Relating to the Basic Properties of Persistent Objects ........................ Basic Operations on an Object ................................................................... Audit Trail ............................................................................................. Convenience Methods for Creating Object Relations ..................................... Validation Methods ................................................................................. Pass-Through Methods to the DMCL API ................................................... Persistent Objects Without Associated Content ................................................. IDfACL ................................................................................................ IDfFormat ............................................................................................. IDfUser and IDfGroup ............................................................................. IDfType ................................................................................................ SysObjectsPersistent Objects With Content .................................................. Basic Operations on SysObjects ................................................................. Types That Derive From IDfSysObject........................................................ IDfSession ................................................................................................. Provide Information ................................................................................ Create Objects and Obtain Object References ............................................... Configuration Information ........................................................................ Transaction Support ................................................................................ Docbase Scope ....................................................................................... Multithreading Support ............................................................................ API Calls .............................................................................................. Inbox and Workflow ................................................................................ Administration ....................................................................................... Session State .......................................................................................... Miscellaneous ........................................................................................ IDfClient ................................................................................................... Creating Sessions and Obtaining References to Existing Sessions..................... Maps and Config Information .................................................................... Service Methods ..................................................................................... Common Package .......................................................................................

142 143 143 145 145 146 146 147 147 148 148 149 149 149 150 150 150 152 153 154 154 154 155 156 156 156 157 157 158 158 159 159 159 159 159 160 160 163 163 165 165

Chapter 10

DFC and DMCL ............................................................................... Relationship to DMCL ................................................................................. Calling DMCL Directly ............................................................................... DMCL to DFC Correspondence .....................................................................

Index .......................................................................................................................... 173

Developing DFC Applications

Table of Contents

List of Figures

Figure 31. Figure 32. Figure 61. Figure 62. Figure 63. Figure 64. Figure 65. Figure 66. Figure 67. Figure 68. Figure 71. Figure 72. Figure 73. Figure 74. Figure 75. Figure 81. Figure 91. Figure 92. Figure 101.

Implementing the getSession method of IDfPrincipalSupport .................................... Principal Identity Diagram .................................................................................. Documentum Business Objects N-Tier Model ........................................................ BOF is integral to DFC ...................................................................................... TBO Interaction Diagram ................................................................................... Business Object Using Another Business Object ..................................................... SBO Interaction Diagram ................................................................................... Any Business Object calling an SBO .................................................................... Class Diagram for Service based Business Objects .................................................. Class Diagram for Type-based Business Objects ..................................................... AutoNumber Schema......................................................................................... Installing a new Docbase Type .......................................................................... Installing a new Docbase Type .......................................................................... Run the test TBO program ................................................................................ Sample running test SBO program ..................................................................... Customer Service User Interface WDK Form ....................................................... DFC Hierarchy Corresponds to Documentum Object Hierarchy ............................... DFC Interface Hierarchy .................................................................................. DFC Builds Business Logic Above DMCL ..........................................................

52 54 70 71 73 73 74 75 77 77 97 105 106 111 119 129 140 141 163

Developing DFC Applications

Table of Contents

List of Tables

Table 11. Table 12. Table 13. Table 21. Table 61. Table 62. Table 63. Table 71. Table 81. Table 82. Table 101. Table 102.

Manual Organization ......................................................................................... COM equivalents of DFC datatypes...................................................................... Classes and Interfaces of DFC Packages ................................................................ DFC Operation Types and Nodes ......................................................................... IDfBusinessObject Methods to Implement ............................................................ TBO Factory Method Exceptions ......................................................................... Methods of IDfDbor .......................................................................................... Sample com_accelera_autonumber Objects and Their Values ................................... WDK Component getDfSession methods ............................................................ DBOR Entry Attribute Samples For "service" And "type" ....................................... DFC Methods and DMCL API Commands ..........................................................

11 17 19 24 86 88 91 98 128 134 165

................................................................................................................... 165

Developing DFC Applications

Preface
Purpose of the Manual
This manual describes Documentum Foundation Classes (DFC), an object-oriented framework for accessing and extending the capabilities of products based on Documentum Content Server.

Intended Audience
This manual is for programmers who understand how to use Java and are generally familiar with the principles of object oriented design.

Revision History
Revision History Revision Date 2003 Mar 31 Description Initial Document Release

Conventions
Conventions Convention Italics Description Represents a variable name for which you must provide a value, or a defined term. Represents code samples, commands, user input, and computer output. When used for a command lines to launch a program, they represent command line arguments that are optional. In code, they are used as the language rules dictate, such as array subscript in Java or C++. For command lines that launch programs, curly braces indicate optional arguments that can be repeated. For code, they represent statement blocks, such as methods and loop blocks in Java and C++.

monospaced [square brackets]

{curly braces}

Developing DFC Applications

Preface

Bug Lists and Documentation Online


Customers with a software support agreement can access the support area of documentum.com to download product documentation. After a product has been commercially released, you can view lists of fixed bugs on the support web page. To access the support area, follow the links to request a user name and password. Documentum responds to access requests within two business days. Once you have a user name and password, you can access the support area without delay. Two weeks after the release, we post a list of customer-reported bugs that have been fixed in that release to the support area of documentum.com.

Product Documentation
When a product is released, we post product documentation to the support area of documentum.com. You can order any of our documentation in the form of bound manuals. We print and stock widely-used manuals, usually several months after we publish the online version. We print other documentation to order. To place an order or to ask about prices, call the documentation order line at (925) 600-6666. You can pay with a purchase order, check, or credit card. We do not sell bound manuals through documentum.com.

10

Developing DFC Applications

Chapter 1 Getting Started With DFC

This chapter introduces DFC. It contains the following major sections: What is DFC?, page 12 Where is DFC?, page 13 Programming with DFC, page 13 Using DFC From Application Programs, page 15 Creating DFC Client Objects, page 17 Using DFC Tracing, page 18 Packages, page 18 Using the DFC Online Reference Documentation, page 20

Organization of the Manual


Table 11. Manual Organization Chapter Chapter 1, Getting Started With DFC Contents What DFC is, where it resides, and how to start using it. Plan of the book. How to perform basic operations like checkin and checkout. How to work with XML documents. How to work with the session manager. Transactions. Authentication. How to use queries to obtain information from Docbases.

Chapter 2, Working With Documents

Chapter 3, Working With Docbase Sessions Chapter 4, Managing Docbase Queries with DFC Chapter 5, Using Validation and ACLs Chapter 6, Understanding Business Objects

How to work with the servers validation and permission mechanisms. The role of the business objects framework (BOF) in middleware. Rules and guidelines for developing BOF services and for extending DFC classes to implement BOF types. Architecture of the business objects registry (DBOR) and how to access and manage it.

Developing DFC Applications

11

Getting Started With DFC

Chapter

Contents A tutorial for developing, deploying and using business objects. Working examples.

Chapter 8, Using and Deploying Business Objects

Using business objects from WDK and Visual Basic. Requirements for deploying business objects to execution platforms. How DFC gives you an object oriented interface to the Documentum object hierarchy. An explanation of DFC in terms of the methods that previous Documentum client products use to access server capabilities. The architecture of the framework and the enhancements to DFC that made the framework possible. Types of business objects, the session manager, and other definitions.

Chapter 9, Overview of the DFC Interface Hierarchy Chapter 10, DFC and DMCL

What is DFC?
Documentum Foundation Classes (DFC) is an object oriented application programming interface (API) and framework for accessing, customizing, and extending Documentum functionality. Documentum has implemented DFC as a set of Java interfaces and implementation classes. DFC also provides a bridge to make the interfaces available in Microsofts Component Object Model (COM) environment. The business objects framework (BOF) is a key part of DFC. BOF enables you to embody business rules and patterns in reusable elements, called type-based objects (TBOs) and service based objects (SBOs). BOF makes it possible to extend some of DFCs implementation classes. As a result, you can introduce new functionality in such a way that unmodified existing programs begin immediately to deliver the new functionality. You can use DFC in any of the following ways: Access Documentum functionality from within one of your companys enterprise applications. For example, your corporate purchasing application can retrieve a contract from your Documentum system. Customize or extend Documentum products like Desktop Client or WDK. For example, you can modify the Desktop Client functionality to implement one of your companys business rules. Write a method or procedure for Content Server to execute as part of a workflow or document lifecycle. For example, the procedure that runs when you promote an XML document might apply a transformation to it and start a workflow to subject the transformed document to a predefined business process.

12

Developing DFC Applications

Getting Started With DFC

The Documentum Content Server Fundamentals manual provides a conceptual explanation of the capabilities of Content Server and how they work. DFC provides a framework for accessing those capabilities. Using this framework makes your code much more likely to survive future architectural changes in the Documentum system. The core of DFC is a set of Java classes, but it includes other elements as well: A collection of DLLs to provide the DFC functionality. A type library for accessing DFC via COM from Visual Basic or Visual C++.

Where is DFC?
DFC runs on a Java virtual machine (JVM), which can be on: The machine that runs Content Server. For example, to execute a method as part of a workflow or document lifecycle. A middle-tier system. For example, to support WDK on an application server. An end users computer. For example, to support Desktop Client.

Programming with DFC


Before you begin to use DFC, it is important to understand the DFC programming approach.

Interfaces
Because DFC is large and complex, and because its underlying implementation is subject to change, you should use DFCs public interfaces wherever possible. DFC provides factory methods to instantiate objects that implement specified DFC interfaces. If you bypass these methods to instantiate implementation classes directly, your programs may fail to work properly, because the factory methods often do more than simply instantiate the standard implementation class. Documentum does not generally support direct access to DFCs implementation classes. Nor does Documentum generally support replacement or extension of DFC implementation classes. The principal exception to these rules is the business object framework (BOF), a mechanism and development pattern for extending selected implementation classes.

Developing DFC Applications

13

Getting Started With DFC

Client/Server Model
The Documentum architecture generally follows the client/server model. DFC-based programs are client programs, even if they run on the same machine as a Documentum server. DFC encapsulates its client functionality in the IDfClient interface, which serves as the entry point for DFC code. IDfClient handles basic details of connecting to Documentum servers. It loads the necessary shared libraries. You obtain the initial IDfClient interface by calling the static getLocalClient method of the DfClient implementation class. The IDfClient interface then serves as a factory for IDfSession objects. If you are familiar with the standard Java database connectivity package (JDBC), you can see an analogy between that programming model and this one. An IDfSession object represents a connection with the Documentum server and provides services related to that session. DFC programmers create new Docbase objects or obtain references to existing Docbase objects through the IDfSession interface.

IDfPersistentObject
With DFC you usually dont create objects directly. Instead, you obtain objects by calling the methods of other objects. Those methods create or obtain the requested object. Methods that create new Docbase objects or fetch existing ones return objects that implement IDfPersistentObject.

Processing a Docbase Object


The following general procedure may help to clarify the DFC approach. Dont worry if you dont completely understand the references to the interface hierarchy. Subsequent sections deal with that subject.
To process a Docbase object:

1. 2. 3. 4.

Obtain an IDfClient object by calling the static getLocalClient method of DfClient. Obtain a session manager by calling the newSessionManager method of the IDfClient object. Use the session manager to obtain a session with the Docbase, that is, a reference to an object that implements the IDfSession interface. If you do not have a reference to the Docbase object, call an IDfSession method (for example, newObject or getObjectByQualification) to create an object or to obtain a reference to an existing object. Use routines of the operations package (see Chapter 2, Working With Documents) to manipulate the objectcheck it out, check it in, and so forth. Release the session if you are done with it.

5. 6.

14

Developing DFC Applications

Getting Started With DFC

Example 11. Processing a Docbase Object

The following fragment from a Java program that uses DFC illustrates this procedure.
IDfClient client = DfClient.getLocalClient(); //Step 1 IDfSessionManager sMgr = client.newSessionManager(); //Step 2 IDfLoginInfo loginInfo = new DfLoginInfo(); loginInfo.setUser( "Mary" ); loginInfo.setPassword( "ganDalF" ); loginInfo.setDomain( "" ); sMgr.setIdentity( strDocbaseName, loginInfo ); IDfSession session = sMgr.newSession( strDocbaseName ); //Step 3 IDfDocument document = null; document = (IDfDocument) session.newObject( "dm_document" ); //Step 4 document.setObjectName( "Report on Wizards" ); document.setContentType( "crtext" ); document.setFile( "C:\Temp\Wiz.txt" ); document.save(); sMgr.release( session ); //Step 6

Steps 1 through 3 obtain an IDfSession object, which encapsulates a session for this application program with the specified Docbase. Step 4 creates an IDfDocument object. Notice that the newObject method of the IDfSession object manufactures the IDfDocument object. Rather than introducing operations at this point, the example code populates and saves the IDfDocument object by calling some of its low level methods. Note that the newObject method returns an IDfPersistentObject object. The program explicitly casts it to an IDfDocument object, then uses the document objects save method, a method that IDfDocument inherits from IDfPersistentObject. Step 6 releases the session, that is, places it back under the control of the IDfSessionManager object. The IDfSessionManager object can reassign it the next time the application calls the objects newSession method. Most DFC methods report errors by throwing a DfException object. Java code like that in the above example normally appears within a try/catch/finally block, with an error handler in the catch block. Visual Basic code uses the On Error Goto statement to handle exceptions. Note: When writing code that calls DFC, it is a good idea to include a finally block to ensure that you can release storage and sessions.

Using DFC From Application Programs


You can use COM or Java to access DFC. Your choices depend on your programming language.

Developing DFC Applications

15

Getting Started With DFC

Java
From Java, use the Java interface. Add the DFC class and interface files (for example, C:\Program Files\Documentum\Shared\dfc.jar) to your CLASSPATH. In your Java source code, import the classes you wish to use.

Visual Basic
Using DFC from Visual Basic requires a small setup procedure. The DFC installer establishes the software environment to allow Visual Basic to access DFC using COM. From a Visual Basic project, you need only establish a reference to dfc.jar.
To establish a reference to dfc.jar:

1.

Choose PropertiesReferences.

The References dialog box appears. 2. Check the checkbox for Documentum Foundation Classes.

C++
From C++, use COM directly, or, if you use MFC, you can use classes, called wrapper classes, that Documentum provides to hide some of the complexities of the COM interface. To use these classes with MFC, include the following files in your Visual C++ project: DfClientX.h, DfClientX.cpp, dfc.h, and dfc_i.c If you dont use MFC or if you wish to write your own wrapper classes, include only dfc.h and dfc_i.c. Note: Interface inheritance requires a workaround if you access DFC from C++, because the Microsoft Java virtual machine does not support COM interface inheritance. See the example in the previous section. Follow these rules for objects and pointers: Always assign a DFC object to a new pointer. First delete the old pointer, then create a new CDfSysObject, as in the following C++ example:
//Get a DFC object CDfSysObject sobj1 = session.getObject(id); CDfSysObject *pSysObj = null; //Delete the old pointer if (pSysObj) delete pSysObj; //Create new CDfSysObject pSysObj = new CDfSysObject(sobj1);

A procedure that returns a DFC object should return a pointer to the object, as demonstrated in the following Visual C++ example:
CDfSysObject *myFunction();

16

Developing DFC Applications

Getting Started With DFC

{ CDfSysObject sobj1 = session.getObject(id); CDfSysObject *retval = new CDfSysObject (sobj1); return retval; }

Syntax Differences
COM and Java give you access to the same DFC classes and interfaces, but COM datatypes differ slightly from Java datatypes. The following table shows the COM equivalents of DFC datatypes.
Table 12. COM equivalents of DFC datatypes Java (DFC datatype) Visual Basic (and Docbasic) Boolean Long String Double IDfinterfacename or Object C++ with MFC wrapper classes BOOL long CString double CDfinterfacename C++ directly to COM

boolean int String double IDfinterfacename

VARIANT_BOOL int BSTR double IDfinterfacename

Creating DFC Client Objects


Perform the following steps before calling DFC methods:

1.

Create a DFC client object as an interface to DFC.

The DFC client object must reside in the same process as the Documentum client library, DMCL. DFC client objects are also called local DFC clients. Java and COM use different interfaces to create the DFC client object, as shown in the examples. 2. Provide login information and use the session manager to establish a DFC session.

Java Example
Use the DfClient.getLocalClient method.
IDfClient myclient = DfClient.getLocalClient();

This line of code creates an IDfClient object. The IDfClient methods provide access to the services of the local DFC client.

Developing DFC Applications

17

Getting Started With DFC

Visual Basic Example


IDfClientX creates DFC objects in COM development environments. You must obtain an IDfClientX object before you can create DFC objects. Use the IDfClientX interfaces getLocalClient method. The following example demonstrates how to create a DFC client object in Visual Basic.
Dim Dim Set Set myclient myclientx myclientX myclient As As = = IDfClient DfClientX CreateObject(Documentum.Dfc) myclientX.getLocalClient

Using DFC Tracing


DFC provides a tracing mechanism through static methods of the DfTrace class. The principal ones are:
setTraceLevel (int traceLevel) setTraceFileName (String fileName) traceMsgCond (int triggerLevel, String msg)

The fact that these methods are static allows you to set up tracing before establishing sessions or creating objects. COM programs must access these methods through the IDfClientX interface. Trace levels range are integers in the range 010. The level controls the amount of information DFC places into the trace file. The level 0 means no tracing, and each increment asks DFC to provide more information. Each level includes all of the information of the smaller numbered levels See the Javadocs for details. If you dont set a trace file, the information goes to the standard output.

Packages
DFC comprises a number of packages, that is, sets of related classes and interfaces. The names of DFC Java classes begin with Df (for example, DfCollectionX). Names of interfaces begin with IDf (for example, IDfSessionManager).

Interfaces expose DFCs public methods and constants. Each interface contains a set of related methods. The following table describes the purpose of the classes and interfaces of DFC packages.

18

Developing DFC Applications

Getting Started With DFC

Table 13. Classes and Interfaces of DFC Packages Java Package Name com.documentum.fc.client Purpose Provides basic functionality: Establishing DFC sessions Retrieving and validating data Managing workflows Manipulating virtual documents Working with document versions com.documentum.operations Provides high-level functionality, such as checking documents or virtual documents in and out. Provides XML support. Constructs and runs queries and SmartLists. Facilitates constructing Docbase queries that return results in an XML format. Supplies utility methods for other DFC classes. Maintains Documentum information on the clients system, using the Windows registry on Win32 platforms, and .ini files otherwise. Provides factory methods for constructing DFC objects. Facilitates access to DFC through COM.

common.documentum.fc.client.qb com.documentum.xml.xdql

com.documentum.fc.common com.documentum.registry

com.documentum.com

Note: The com.documentum.operations package and the IDfSysObject interface in the com.documentum.fc.client package have some methods for the same basic tasks (for example, checkin, checkout). The IDfSysObject methods are mostly for internal use and for supporting legacy applications. The methods in the operations package perform the corresponding tasks at a higher levelkeeping track of client-side files and implementing Content Server XML functionality. The name of the com.documentum.com interface might lead you to believe that it is only for accessing DFC through COM. In fact, you can use its factory methods (all of its getxxx methods, except for those dealing with the DFC version or trace levels) from Java code as well.

The DFC interfaces form a hierarchy; some derive methods and constants from others. Use the Tree link from the home page of the DFC online reference (see Using the DFC Online Reference Documentation, page 20) to examine the interface hierarchy. Click any interface to go to its definition. Each interface inherits the methods and constants of the interfaces above it in the hierarchy. For example, IDfPersistentObject has a save method. IDfSysObject is a subclass of IDfPersistentObject, so it inherits the save method (see Persistent Objects, page 146 and SysObjectsPersistent Objects With Content, page 152).

Developing DFC Applications

19

Getting Started With DFC

In Java, you can call the save method of an object of type IDfSysObject.

Using the DFC Online Reference Documentation


This section explains how to use the DFC online reference documentation to find greater detail about DFC structure and syntax. Documentum uses the Javadoc facility to produce a DFC reference. This reference is available online in HTML form, both by itself and as part of the Developer Studio online help. From the home page of the reference, you can choose a variety of views. The Help link provides a description of how the reference is organized. The DFC library is large, and programmers sometimes have difficultly determining where to find or look for functionality. If this happens, consider using the following decision sequence.
To find the interface that provides a specified operation:

1.

If you wish to operate on an object in the Docbase, determine the most general interface that should support the operation, and look there.

For example, you can save any persistent object, so look for a save method in IDfPersistentObject. If the functionality involves content, security, versioning, or checkout/checkin, look at IDfSysObject or interfaces derived from it. 2. If you wish to create an object, obtain a reference to an object, or perform a general operation, a. b. If the operation depends on having a session, look in IDfSession. Otherwise, look in IDfClientX.

20

Developing DFC Applications

Chapter 2 Working With Documents

This chapter describes the way to use DFC to perform the most common operations on documents. It contains the following main sections: Introduction to Documents, page 21 Introduction to Operations, page 23 Types of Operations, page 24 Basic Steps for Manipulating Documents, page 24 Handling Document Manipulation Errors, page 41

Introduction to Documents
The Documentum Content Server Fundamentals manual explains the Documentum facilities for managing documents. This section provides a concise summary of what you need to know to understand the remainder of this chapter. Documentum maintains a repository of objects that it classifies according to a type hierarchy. For this discussion, SysObjects are at the top of the hierarchy (see SysObjectsPersistent Objects With Content, page 152). A document is a specific kind of SysObject. Its primary purpose is to help you manage content.

Virtual Documents
A virtual document is a container document that includes one or more objects called components structured as an ordered hierarchy. A component is another virtual document or any SysObject subtype except folders, cabinets, or subtypes of folders and cabinets. A virtual document can have any number of components, nested to any level. Documentum imposes no limit on the depth of nesting in a virtual document. Documentum uses two sets of terminology for virtual documents. In the first set, a virtual document that contains a component is called the components parent, and the component is called the virtual documents child. Children, or children of children to any depth, are called descendants. Note: Descendants are sometimes called descendents in internal variables, Javadoc comments, and registry keys.

Developing DFC Applications

21

Working With Documents

The second set of terminology derives from graph theory. The virtual document and each of its descendants is called a node. The directed relationship between a parent node and a child node is called an edge. In both sets of terminology, the original virtual document is sometimes called the root. Documentum maintains more than one version of a document. A version tree is an original document and all of its versions. Every version of the document has a unique object ID, but every version has the same chronicle IDthe object ID of the original document. You can associate a particular version of a component with the virtual document (this is called early binding) or you can associate the components entire version tree with the virtual document. The latter allows you to select which version to include at the time you assemble the document (this is called late binding). Documentum provides an extremely flexible set of rules for controlling the way it assembles documents. An assembly is a snapshot of a virtual document. It consists of the set of specific component versions that result from assembling the virtual document according to a set of binding rules. To preserve it, you must attach it to a SysObjectusually either the root of the virtual document or a SysObject created to hold the assembly. A SysObject can have at most one attached assembly. Documentum represents the components of virtual documents by containment objects and the components of assemblies by assembly objects. An assembly object refers to the SysObject to which the assembly is attached, and to the virtual document from which the assembly came. If an object appears more than once as a node in a virtual document or assembly, each node has a separate associated containment or assembly object. No object can appear as a descendant of itself in a virtual document. You can version a virtual document and manage its versions just as you do a simple document. Deleting a virtual document version also removes any containment objects or assembly objects associated with that version. When you copy a virtual document, the server can make a copy of each component or it can create an internal reference or pointer to the source component. It maintains information in the containment object about which of these possibilities to choose. One option is to require the copy operation to specify the choice. Whether it copies a component or creates a reference, Documentum creates a new containment object corresponding to that component. Note: DFC allows you to process the root of a virtual document as an ordinary document. For example, suppose that doc is an object of type IDfDocument and also happens to be the root of a virtual document. If you tell DFC to check doc out, it does not check out any of the descendants. If you want DFC to check out the descendants along with the root document, you must first execute an instruction like
IDfVirtualDocument vDoc = doc.asVirtualDocument(CURRENT, false)

If you tell DFC to check vDoc out, it processes the current version of doc and each of its descendants. The DFC Javadocs explain the parameters of asVirtualDocument.

22

Developing DFC Applications

Working With Documents

XML Documents
When you import an XML document, DFC creates a virtual document. It imports other documents that the XML document refers to as entity references or links, and makes them components of the virtual document. It uses attributes of the containment object associated with a component to remember whether it came from an entity or a link and to maintain other necessary information. Assembly objects have the same XML-related attributes as containment objects do. Documentums XML support has many more features. It also requires you to provide a controlling XML application. Information about those subjects appears in Documentum Content Server Fundamentals and in Managing XML Content in Documentum.

Introduction to Operations
To manipulate documents in Documentum, you must understand operations. Operations are like the document carriers you use to put small pieces of paper through the feeder of a copying machine. Operations provide interfaces and a processing environment to ensure that Documentum can handle a variety of documents and collections of documents in a standard way. You obtain an operation of the appropriate kind, place one or more documents into it, and run it through the machine, that is, execute the operation. The operations apply to objects of type IDfSysObject, not just the subtype IDfDocument, but all of the examples in this chapter pertain only to documents. For example, to check out a document, take the following steps: 1. 2. 3. Obtain a checkout operation. Add the document to the operation. Execute the operation.

DFC carries out the behind-the-scenes tasks associated with checking out a document. For a virtual document, for example, DFC adds all of its components to the operation and ensures that links between them are still valid when it stores the documents into the checkout directory on the file system. It corrects filename conflicts, and it keeps a local record of which documents it checked out. This is only a partial description of what DFC does when you check out a document. Because of the number and complexity of the underlying tasks, DFC wraps seemingly elementary document-manipulation tasks in constructs called operations. An IDfClientX object provides methods for creating operations. For this reason, we call it a factory for operations. Once you have the factory object (say cX) and a SysObject representing the document (say doc), the code for the checkout looks like this:
// Obtain a checkout operation IDfCheckoutOperation checkout = cX.getCheckoutOperation; // Add the document to the checkout operation checkout.add(doc); //This might fail and return a null // Check the document out checkout.execute(); //This might produce errors without

Developing DFC Applications

23

Working With Documents

//throwing an exception

In real code, you would check to see if the add method returns a null or the execute method returns errors.

Types of Operations
DFC provides operation types and corresponding nodes (to be explained in subsequent sections) for many tasks you might wish to perform on documents or, where appropriate, files or folders. The following table summarizes these.
Table 21. DFC Operation Types and Nodes Task Import into a Docbase Export from a Docbase Check into a Docbase Check out of a Docbase Cancel a checkout Delete from a Docbase Copy from one Docbase location to another Move from one Docbase location to another Validate an XML document against a DTD or Schema Transform an XML document using XSLT Operation Type IDfImportOperation IDfExportOperation IDfCheckinOperation IDfCheckoutOperation IDfCancelCheckoutOperation IDfDeleteOperation IDfCopyOperation Operation Node Type IDfImportNode IDfExportNode IDfCheckinNode IIDfCheckoutNode IDfCancelCheckoutNode IDfDeleteNode IDfCopyNode

IDfMoveOperation

IDfMoveNode

IDfValidationOperation

IDfValidationNode

IDfXMLTransformOperation

IDfXMLTransformNode

Basic Steps for Manipulating Documents


This section describes the basic steps common to using the facilities of the operations package to manipulate documents. It sets forth the basic steps, then discusses the steps in greater detail.

Steps for Manipulating Documents


To perform a document-manipulation task:

1.

Use the appropriate factory method of IDfClientX to obtain an operation of the type appropriate to the document-manipulation task.

24

Developing DFC Applications

Working With Documents

For example, if you wish to check documents into a Docbase, start by calling getCheckinOperation. 2. Set parameters to control the way the operation performs the task.

Each operation type has setXxx methods for setting its parameters. The operation behaves in predefined (default) ways if you do not set optional parameters. Some parameters (the session for an import operation, for example) are mandatory. 3. Add documents to the operation: a. Use its inherited add method to place a document, file, or folder into the operation. Note: Each operation has a type (for example, IDfCheckinOperation) that inherits most of its methods (in particular, its add and execute methods) from IDfOperation. The add method returns the newly created node (or a null if it fails). b. Set parameters to change the way the operation handles this item and its descendants.

Each type of operation node has methods for setting parameters that are important for that type of operation. These are generally the same as the methods for the corresponding type of operation. If you do not set parameters, the operation handles this item according to the setXxx methods. c. 4. Repeat the previous two substeps for all items you wish to place into the operation.

Invoke the operations inherited execute method to perform the task. Note: Each operation has a type (for example, IDfCheckinOperation) that inherits most of its methods (in particular, its add and execute methods) from IDfOperation.

Note that this step may add and process additional nodes. For example, if part of the execution entails scanning an XML document for links, DFC may add the linked documents to the operation. 5. Process the results. a. Handle errors.

If it detects errors, the execute method returns the boolean value false. You can use the operations inherited getErrors method to obtain a list of failures. Note: Each operation has a type (for example, IDfCheckinOperation) that inherits most of its methods (in particular, its add and execute methods) from IDfOperation. For details of how to process errors, see Processing the Results, page 27. b. Perform tasks specific to the operation.

For example, after an import operation, you may wish to take note of all of the new objects that the operation created in the repository. You might wish to display or modify their properties.

Developing DFC Applications

25

Working With Documents

Details of Manipulating Documents


This section discusses some issues and background for the steps of the general procedure in Steps for Manipulating Documents, page 24. Note: Each operation has a type (for example, IDfCheckinOperation) that inherits most of its methods (in particular, its add and execute methods) from IDfOperation.

Obtaining the Operation


The factory methods of IDfClientX manufacture an object of the appropriate type.

Setting Parameters for the Operation


Different operations accept different parameters to control the way they carry out their tasks. Some parameters are optional, some mandatory. Note: You must use the setSession method of IDfImportOperation or IDfXMLTransformOperation to set a Docbase session before adding nodes to either of these types of operation. No other operation type has a setSession method.

Adding Documents to the Operation


An operation contains a structure of nodes and descendants. When you obtain the operation, it has no nodes (DFC does not regard the operation itself as a node). When you use the operations add method to add documents to the operation, it creates new root nodes. The add method returns the node as an IDfOperationNode object. You must cast it to the appropriate operation node type to use any methods the type does not inherit from IDfOperationNode (see Working With Nodes, page 27). Note: If the add method cannot create a node for the specified document, it returns a null argument. Be sure to test for this case, because it does not usually throw an exception. DFC may add additional nodes to the operation. For example, if you add a Docbase folder, DFC adds nodes for the documents linked to that folder, as children of the folders node in the operation. Each node can have zero or more child nodes. If you add a virtual document, the add method creates as many descendant nodes as necessary to create an image of the virtual documents structure within the operation. You can add objects from more than one Docbase to an operation. You can use a variety of methods to obtain and step through all nodes of the operation (see Working With Nodes, page 27). You may wish to set parameters on individual nodes differently from the way you set them on the operation.

26

Developing DFC Applications

Working With Documents

Executing the Operation


The operations package processes the objects in an operation as a group, possibly invoking many DFC calls for each object. Operations encapsulate Documentum client conventions for registering, naming, and managing local content files. DFC executes the operation in a predefined set of steps, applying each step to all of the documents in the operation before proceeding to the next step. It processes each document in an operation only once, even if the document appears at more than one node. Once DFC has executed a step of the operation on all of the documents in the operation, it cannot execute that step again. If you wish to perform the same task again, you must construct a new operation to do so. Normally, you use the operations execute method and let DFC proceed through the execution steps. DFC provides a limited ability for you to execute an operation in steps, so that you can perform special processing between steps. Documentum does not recommend this approach, because the number and identity of steps in an operation may change with future versions of DFC. If you have a programming hurdle that you cannot get over without using steps, work with Documentum Technical Support or Consulting to design a solution.

Processing the Results


If DFC encounters an error while processing one node in an operation, it continues to process the other nodes. For example, if one object in a checkout operation is locked, the operation checks out the others. Only fatal conditions cause an operation to throw an exception. DFC catches other exceptions internally and converts them into IDfOperationError objects. The getErrors method returns an IDfList object containing those errors, or a null if there are no errors. The calling program can examine the errors, and decide whether to undo the operation, or to accept the results for those objects that did not generate errors. Once you have checked the errors you may wish to examine and further process the results of the operation. The next section, Working With Nodes, page 27, shows how to access the objects and results associated with the nodes of the operation.

Working With Nodes


Note: Each operation node type (for example, IDfCheckinOperationNode) inherits most of its methods from IDfOperationNode. The getChildren method of an IDfOperationNode object returns the first level of nodes under the given node. You can use this method recursively to step through all of the descendant nodes. Alternatively, you can use the operations getNodes method to obtain a flat list of descendant nodes, that is, an IDfList object containing of all of its descendant nodes without the structure.

Developing DFC Applications

27

Working With Documents

These methods return nodes as objects of type IDfOperationNode, not as the specific node type (for example, IDfCheckinOperationNode). The getId method of an IDfOperationNode object returns a unique identifier for the node, not the object ID of the corresponding document. IDfOperationNode does not have a method for obtaining the object ID of the corresponding object. Each operation node type (for example, IDfCheckinOperationNode) has its own getObjectID method. You must cast the IDfOperationNode object to a node of the specific type before obtaining the object ID.

Operations for Manipulating Documents


This section provides sample code and discusses specific details of the following kinds of document manipulation operations: Importing, page 28 Exporting, page 30 Checking Out, page 31 Checking In, page 32 Cancelling Checkout, page 34 Copying, page 34 Moving, page 36 Deleting, page 36 Validating an XML Document Against a DTD or Schema, page 38 Performing an XSL Transformation of an XML Document, page 39

The examples use the term file to refer to files on the file system and the terms document and folder to refer to Docbase documents and folders, as represented by DFC objects of type IDfDocument and IDfFolder.

Importing
The execute method of an IDfImportOperation object imports files into the repository. It creates objects as required, transfers the content to the repository, and removes local files if appropriate. If any of the nodes of the operation refer to existing objects (for example, through XML or OLE links), it imports those into the repository too.
Example 21. Importing an XML document void testImport1( IDfClientX clientx, // factory for operation IDfSessionManager sMgr, // to obtain a session String strDocbaseName, // to obtain a session IDfId idFolder, // dest folder id IDfFile idFile ) // file to import throws DfException { IDfSession session = sMgr.getSession( strDocbaseName ); try { // Construct a new import operation IDfImportOperation opImport = clientx.getImportOperation();

28

Developing DFC Applications

Working With Documents

// Set operation object properties opImport.setSession( session ); opImport.setDestinationFolderId( idFolder ); // Add file to import and downcast it to the specific type IDfImportNode node = (IDfImportNode)opImport.add( idFile ); if( node == null ) { // See Handling Document Manipulation Errors, page 41 } // Set node properties node.setXMLApplicationName( "CellPhoneCatalog" ); // Execute the operation if( !opImport.execute() ) { // See Handling Document Manipulation Errors, page 41 } // Optionally, get a list of object IDs IDfList list = opImport.getNewObjects(); IDfSysObject obj; int iCount = list.getCount(); for( int i = 0; i < iCount; ++i ) { obj = (IDfSysObject)list.get( i ); System.out.println( obj.getObjectId().toString() ); System.out.println( obj.getObjectName() ); } } finally { sMgr.release( session ); } }

Special Considerations for Import Operations


Follow the steps in Steps for Manipulating Documents, page 24.

Setting up the Operation


Use the objects setSession method to specify a Docbase session and the objects setDestinationFolder method to specify the Docbase cabinet or folder into which the operation should import documents. You must set the session before adding files to the operation. You must set the destination folder, either on the operation or on each node. You can add an IDfFile object or specify a file system path. You can also specify whether to keep the file on the file system (the default choice) or delete it after the operation is successful. If you add a file system directory to the operation, DFC imports all files in that directory and proceeds recursively to add each subdirectory to the operation. You can also control version labels, object names, object types and formats of the imported objects.

Developing DFC Applications

29

Working With Documents

XML Processing
The statement in the example under the comment Set node properties tells DFC not to determine the controlling XML application automatically but instead to use the application called CellPhoneCatalog. You can import XML files without doing XML processing. If nodeImport is an IDfImportNode object, you can turn off XML processing on the node and all its descendants by calling
nodeImport.setFormat(dm_document);

This also turns off content detection, so the operation does not recognize embedded OLE objects. Turning off these kinds of processing can shorten the time it takes DFC to perform the operation.

Processing the Imported Documents


Executing an import operation results in the creation of new objects in the repository. If opImport is the IDfImportOperation object, you can obtain a complete list of the new objects by calling
IDfList list = opImport.getNewObjects;

The list contains the object IDs of the newly created SysObjects. In addition, the IDfImportNode objects associated with the operation are still available after you execute the operation (see Working With Nodes, page 27). You can use their methods to find out many other facts about the new SysObjects associated with those nodes. For example, you can find out object IDs, object names, version labels, file paths, and formats.

Exporting
The execute method of an IDfExportOperation object creates copies of documents on the local file system. If the operations add method receives a virtual document as an argument, it also adds all of the documents descendants (determined by applying the applicable binding rules), creating a separate node for each.
Example 22. Exporting a document to the default checkout directory

This example does not create registry information about the resulting file.
void testExport1( IDfClientX clientx, // factory for operation IDfId idDoc, // id of document to export String strDir ) // destination directory throws DfException { // Construct a new export operation IDfExportOperation opExport = clientx.getExportOperation(); // Add the document and cast the node to the appropriate type IDfExportNode node = (IDfExportNode)opExport.add( idDoc ); // Set properties on the node node.setFilePath( strDir );

30

Developing DFC Applications

Working With Documents

node.setRecordInRegistry( IDfExportOperation.DONT_RECORD_IN_REGISTRY ); if( node == null ) { // See Handling Document Manipulation Errors, page 41 // Execute the operation if( !opExport.execute() ) { // See Handling Document Manipulation Errors, page 41

Special Considerations for Export Operations


Follow the steps in Steps for Manipulating Documents, page 24. By default, an export operation creates files on the local system and makes no provision for Documentum to manage them. You can tell DFC to create registry entries for the files by invoking the setRecordInRegistry method of an object of type either IDfExportOperation or IDfExportNode, using the parameters described in the Javadocs. If any node corresponds to a checked out document, DFC copies the latest Docbase version to the local file system. DFC does not treat this as an error. You can find out where on the file system the export operation creates files. Use the getDefaultDestinationDirectory and getDestinationDirectory methods of IDfExportOperation objects and the getFilePath method of IDfExportNode objects to do this.

Checking Out
The execute method of an IDfCheckoutOperation object checks out the Docbase documents in the operation. Checking out a document is like exporting one, but the checkout operation: Locks the document Always creates registry entries to enable DFC to manage the files it creates on the file system

If the operations add method receives a virtual document as an argument, it also adds all of the documents descendants (determined by applying the applicable binding rules), creating a separate node for each.
Example 23. Checking out a virtual document

Check out a virtual document to the default checkout directory.


void testCheckoutVdoc( IDfClientX clientx, // factory for operation IDfDocument doc, // String strDir ) throws DfException { // Construct a new checkout operation IDfCheckoutOperation checkout = clientx.getCheckoutOperation(); // Set Docbase folder as the base for source of the checkout. checkout.setDestinationDirectory( strDir ); // Convert the document to a node tree IDfVirtualDocument vDoc =

Developing DFC Applications

31

Working With Documents

doc.asVirtualDocument( "CURRENT", false ); // Add the vDoc and all of its nodes IDfCheckoutNode node = (IDfCheckoutNode)checkout.add( vDoc ); if( node == null ) { // See Handling Document Manipulation Errors, page 41 } // Execute the operation if( !checkout.execute() ) { // See Handling Document Manipulation Errors, page 41 }

Special Considerations for Checkout Operations


Follow the steps in Steps for Manipulating Documents, page 24. If any node corresponds to a checked out document, there is no need to check it out again. DFC does not treat this as an error. DFC applies XML processing to XML documents. If necessary it modifies the resulting files to ensure that it has enough information to check the documents in properly. You can use many of the same methods for setting up checkout operations and processing results that you use for export operations.

Checking In
The execute method of an IDfCheckinOperation object checks documents into the repository. It creates new objects as required, transfers the content to the repository, and removes local files if appropriate. It checks in existing objects that any of the nodes refer to (for example, through XML links).
Example 24. Checking in a document

Check in a document as the next minor version, setting the version labels to DRAFT and WIP, and taking the content from C:/myfile.doc.
void testCheckinDoc( IDfClientX clientx, // factory for operation IDfDocument doc, // checked out doc to version String strFileName ) // Check in "From" file throws DfException // Construct a new checkin operation IDfCheckinOperation checkin = clientx.getCheckinOperation(); // Set operation properties checkin.setCheckinVersion( IDfCheckinOperation.NEXT_MINOR ); checkin.setVersionLabels( "DRAFT,WIP" ); // Add the document to the operation IDfCheckinNode node = (IDfCheckinNode)checkin.add( doc ); if( node == null ) { // See Handling Document Manipulation Errors, page 41 } // Set the node properties (same as "Check In From File") node.setFilePath( strFileName ); // like: "C:/myFile.doc" // Execute the operation if( !checkin.execute() ) { // See Handling Document Manipulation Errors, page 41 }

32

Developing DFC Applications

Working With Documents

IDfList list = checkin.getNewObjects(); int count = list.getCount(); if( count == 1 ) { IDfId idObj = node.getNewObjectId(); } else { for( int i = 0; i < count; ++i ) processObject( list.getId( i ) ); { } } }

After executing this code, you can obtain the ID of the document you just checked in:
IDfId newId = node.getNewObjectId();

Special Considerations for Checkin Operations


Follow the steps in Steps for Manipulating Documents, page 24.

Setting up the Operation


To check in a document, you pass an object of type IDfSysObject, not the file on the local file system, to the operations add method. DFC records the path and filenameof the local file that represents the content of an object. If you move or rename the file, DFC loses track of it and reports an error if you try to check it in. If you specify a document that is not checked out, DFC does not check it in. DFC does not treat this as an error. You can specify checkin version, symbolic label, or alternate content file, and you can direct DFC to preserve the local file. If between checkout and checkin you remove a link between documents, DFC adds the orphaned document to the checkin operation as a root node, but the relationship between the documents no longer exists in the repository.

Processing the Checked In Documents


Executing a checkin operation normally results in the creation of new objects in the repository. If opCheckin is the IDfCheckinOperation object, you can obtain a complete list of the new objects by calling
IDfList list = opCheckin.getNewObjects;

The list contains the object IDs of the newly created SysObjects. In addition, the IDfCheckinNode objects associated with the operation are still available after you execute the operation (see Working With Nodes, page 27). You can use their methods to find out many other facts about the new SysObjects associated with those nodes.

Developing DFC Applications

33

Working With Documents

Cancelling Checkout
The execute method of an IDfCancelCheckoutOperation object cancels the checkout of documents by releasing locks, deleting local files if appropriate, and removing registry entries. If the operations add method receives a virtual document as an argument, it also adds all of the documents descendants (determined by applying the applicable binding rules), creating a separate operation node for each.
Example 25. Cancelling checkout

Cancel checkout of a virtual document and preserve the local files.


void testCancelCheckout( IDfClientX clientx, // factory for operation IDfDocument doc ) // checked out doc throws DfException { IDfCancelCheckoutOperation cancel = clientx.getCancelCheckoutOperation(); cancel.setKeepLocalFile( true ); // Convert the document to a node tree IDfVirtualDocument vDoc = doc.asVirtualDocument( "CURRENT", false ); IDfCancelCheckoutNode node = (IDfCancelCheckoutNode)cancel.add( vDoc ); if( node == null ) { // See Handling Document Manipulation Errors, page 41 } // Execute the operation if( !cancel.execute() ) { // See Handling Document Manipulation Errors, page 41 } }

Special Considerations for CancelCheckout Operations


Follow the steps in Steps for Manipulating Documents, page 24. If a document in the cancel checkout operation is not checked out, DFC does not process it. DFC does not treat this as an error.

Copying
The execute method of an IDfCopyOperation object copies the current versions of documents or folders from one repository location to another. If the operations add method receives a virtual document as an argument, it also adds all of the documents descendants (determined by applying the applicable binding rules), creating a separate node of the operation for each. If the add method receives a folder (unless you override this default behavior), it also adds all documents and folders linked to that folder. This continues recursively until

34

Developing DFC Applications

Working With Documents

the entire hierarchy of documents and subfolders under the original folder is part of the operation. The execute method replicates this hierarchy at the target location.
Example 26. Copying a folder void testCopyDocbaseFolder( IDfClientX clientx, // factory for op IDfSession session, // used to fetch objs IDfFolder folderSource, // copy from IDfId idDestinationFolder ) // copy to throws DfException { IDfCopyOperation copy = clientx.getCopyOperation(); copy.setDestinationFolderId( idDestinationFolder ); // copy.setDeepFolders( true ); // same as default // copy.setCopyPreference( IDfCopyOperation.COPY_COPY ); IDfCopyNode node = (IDfCopyNode)copy.add( folderSource ); if( node == null ) { // See Handling Document Manipulation Errors, page 41 } node.setNewObjectName( null ); // same as default = same name // Execute the operation if( !copy.execute() ) { // See Handling Document Manipulation Errors, page 41 } // Process the copy operation results... IDfList list = copy.getNodes(); int count = list.getCount(); IDfSysObject sysobj; IDfId idNewFolder; String strNewFolder; IDfId idNewObject; String strIdNewObject; String strNewObjectName; IDfFolder folder; for( int i = 0; i < count; ++i ) { node = (IDfCopyNode)list.get( i ); idNewObject = node.getNewObjectId(); strIdNewObject = idNewObject.toString(); strNewObjectName = node.getNewObjectName(); idNewFolder = node.getDestinationFolderId(); folder = (IDfFolder)session.getObject( idNewFolder ); strNewFolder = folder.getObjectName(); System.out.println( i + ". " ); System.out.print( strIdNewObject + ", " ); System.out.print( strNewObjectName + ", " ); System.out.println( strNewFolder ); System.out.println( System.getProperty ( "line.separator" ) ); } }

Special Considerations for Copy Operations


Follow the steps in Steps for Manipulating Documents, page 24. You must set the destination folder, either on the operation or on each of its nodes. You can use the setDeepFolders method of the operation object (node objects do not have this method) to override the default behavior of recursively adding folder contents to the operation.

Developing DFC Applications

35

Working With Documents

Moving
The execute method of an IDfMoveOperation object moves the current versions of documents or folders from one repository location to another by unlinking them from the source location and linking them to the destination. Versions other than the current version remain linked to the original location. If the operations add method receives a virtual document as an argument, it also adds all of the documents descendants (determined by applying the applicable binding rules), creating a separate node for each. If the add method receives a folder (unless you override this default behavior), it adds all documents and folders linked to that folder. This continues recursively until the entire hierarchy of documents and subfolders under the original folder is part of the operation. The execute method links this hierarchy to the target location.
Example 27. Moving a virtual document void testMoveVDoc( IDfClientX clientx, // for operation factory IDfDocument doc, // doc to move IDfId idSrcFolder, // move from folder IDfId idDestFolder ) // move to folder throws DfException { IDfMoveOperation move = clientx.getMoveOperation(); move.setSourceFolderId( idSrcFolder ); move.setDestinationFolderId( idDestFolder ); // Convert the document to a node tree IDfVirtualDocument vDoc = doc.asVirtualDocument( "CURRENT", false ); IDfMoveNode node = (IDfMoveNode)move.add( vDoc ); if( node == null ) { See Handling Document Manipulation Errors, page 41 } // Execute the operation if( !move.execute() ) { // See Handling Document Manipulation Errors, page 41 } }

Special Considerations for Move Operations


Follow the steps in Steps for Manipulating Documents, page 24. Options for moving are essentially the same as for copying. If the operation entails moving a checked out document, DFC leaves the document unmodified and reports an error.

Deleting
The execute method of an IDfDeleteOperation object removes documents and folders from the repository.

36

Developing DFC Applications

Working With Documents

If the operations add method receives a virtual document as an argument, it also adds all of the documents descendants (determined by applying the applicable binding rules), creating a separate node for each.
Example 28. Deleting a document void testDeleteDoc( IDfClientX clientx, // for operation factory IDfDocument doc ) // doc to delete throws DfException { IDfDeleteOperation opDelete = clientx.getDeleteOperation(); IDfDeleteNode node = (IDfDeleteNode)opDelete.add( doc ); if( node == null ) { See Handling Document Manipulation Errors, page 41 } // Execute the operation if( !opDelete.execute() ) { // See Handling Document Manipulation Errors, page 41 } } Example 29. Deleting all versions of all documents

Delete all versions of all documents in a folder. Assume that folder is an object of type IDfFolder and cX, an IDfClientX object, is a factory for operations.
void testDeleteFolder( IDfClientX clientx, // for operation factory IDfFolder folder ) // folder to delete throws DfException { IDfDeleteOperation opDelete = clientx.getDeleteOperation(); // Tell DFC to delete all version of the objects. // Note: Set this before you add the documents or folders. opDelete.setVersionDeletionPolicy( IDfDeleteOperation.ALL_VERSIONS ); IDfDeleteNode node = (IDfDeleteNode)opDelete.add( folder ); if( node == null ) { // See Handling Document Manipulation Errors, page 41 } // Execute the operation if( !opDelete.execute() ) { // See Handling Document Manipulation Errors, page 41 } }

Special Considerations for Delete Operations


Follow the steps in Steps for Manipulating Documents, page 24. If the operation entails deleting a checked out document, DFC leaves the document unmodified and reports an error.

Developing DFC Applications

37

Working With Documents

Validating an XML Document Against a DTD or Schema


DFC uses a modified version of the Xerces XML parser, which it includes in dfc.jar. See the DFC release notes for details about the specific version and the Documentum modifications. The execute method of an IDfValidateOperation object runs the parser in validation mode to determine whether or not documents are well formed and conform to the DTD or schema. If you do not specify it explicitly, DFC determines the XML application automatically and looks in the applications folder in the repository for the DTD or schema. If any argument or the DTD or schema is in the repository, the execute method makes a temporary copy on the file system and performs the validation there. If the parser detects errors, the operations execute method returns a value of false, and you can use the operations getErrors method to obtain the error information that the parser returns.
Example 210. Validating an XML document

Validate an XML document, using C:\Temp for a working directory.


void testValidateXmlDefault( IDfClientX clientx, // for factory IDfDocument doc ) // doc to validate throws DfException { IDfValidationOperation validate = clientx.getValidationOperation(); validate.setDestinationDirectory( "C:/Temp" ); // Convert the document to a node tree IDfVirtualDocument vDoc = doc.asVirtualDocument( "CURRENT", false ); IDfValidationNode node = (IDfValidationNode)validate.add( vDoc ); if( node == null ) { // See Handling Document Manipulation Errors, page 41 } // Execute the operation if( !validate.execute() ) { // See Handling Document Manipulation Errors, page 41 } }

Special Considerations for Validation Operations


Follow the steps in Steps for Manipulating Documents, page 24. You can use the operations setDestinationDirectory method to specify the file system directory to which the operation exports XML files and DTDs or schemas to pass to the parser.

38

Developing DFC Applications

Working With Documents

Performing an XSL Transformation of an XML Document


Documentum packages its own versions of the Xalan XSL transformation (XSLT) engine in dfc.jar. See the DFC release notes for details about the specific version and the Documentum modifications. The execute method of the IDfXMLTransformOperation interface uses the Xalan transformation engine and the specified XSLT stylesheet to transform an XML file or document. It places the output into a new document or attaches it to the original document as a rendition. It can also output an object of type IDfFile or any java.io.Writer or java.io.OutputStream stream.
Example 211. Transform to an HTML file

Transform the file C:/NewsMLNewsletter.xml into an HTML file C:/ NewsMLNewsletter.htm, using an XSLT stylesheet from the Docbase.
void testTransformXml2HtmlUsingStylesheetObject( IDfClientX clientx, // for operation factory IDfSession session, // required for transformation IDfDocument docStylesheet ) // XSL stylesheet in Docbase throws DfException, IOException { IDfXMLTransformOperation transform = clientx.getXMLTransformOperation(); transform.setSession( session ); transform.setTransformation( docStylesheet ); FileOutputStream out = new FileOutputStream( "C:\NewsMLNewsletter.htm" ); transform.setDestination( out ); IDfXMLTransformNode node = (IDfXMLTransformNode) transform.add( "C:\NewsMLNewsletter.xml" ); if( node == null ) { // See Handling Document Manipulation Errors in

// Using DFC in Documentum Applications


} node.setOutputFormat( "html" ); // Execute the operation if( !transform.execute() ) { // See Handling Document Manipulation Errors in

// Using DFC in Documentum Applications


} } Example 212. Transform to an HTML file, import result into Docbase

Transform the file C:/NewsMLNewsletter.xml into a new HTML document in the repository, using the XSLT stylesheet C:/NewsMLStylesheet.xsl, and import it into the Docbase.
void testTransformationXml2UsingStylesheetFile( IDfClientX clientx, // for operation factory IDfSession session, // required for transformation IDfId idDestFolder ) // dest folder id throws DfException { IDfXMLTransformOperation opTransform = clientx.getXMLTransformOperation(); opTransform.setSession( session ); opTransform.setTransformation( "C:/NewsMLStylesheet.xsl" ); IDfImportOperation opImport = clientx.getImportOperation(); opImport.setSession( session );

Developing DFC Applications

39

Working With Documents

opImport.setDestinationFolderId( idDestFolder ); opTransform.setDestination( opImport ); IDfXMLTransformNode nodeTransform = (IDfXMLTransformNode) opTransform.add( "C:/ContractInfo.xml" ); if( nodeTransform == null ) { // See Handling Document Manipulation Errors in

// Using DFC in Documentum Applications


} // Specify the output format // (NOTE: on the transform node, not the import node). nodeTransform.setOutputFormat( "html" ); // Execute the operation if( !opTransform.execute() ) { // See Handling Document Manipulation Errors in

// Using DFC in Documentum Applications


} } Example 213. Transform an XML document into an HTML rendition

Transform an XML document into an HTML rendition, using an XSLT stylesheet from the Docbase.
void testTransformationXml2HtmlRendition( IDfClientX clientx, // for operation factory IDfSession session, // required for transformation // String strOutputDir, // directory to put HTML file in IDfDocument docXml, // root of the XML document IDfDocument docStylesheet ) // XSL stylesheet in Docbase throws DfException { IDfXMLTransformOperation opTransform = clientx.getXMLTransformOperation(); opTransform.setSession( session ); opTransform.setTransformation( docStylesheet ); IDfXMLTransformNode nodeTransform = (IDfXMLTransformNode) opTransform.add( docXml ); if( nodeTransform == null ) { // See Handling Document Manipulation Errors in

// Using DFC in Documentum Applications


} // To make a rendition, dont call setDestination(), and // the output format is different from that input format //opTransform.setDestination( strOutputDir ); // Specify the output format // (NOTE: on the transform node, not the import node) nodeTransform.setOutputFormat( "html" ); // Execute the operation if( !opTransform.execute() ) { // See Handling Document Manipulation Errors in

// Using DFC in Documentum Applications


} }

Special Considerations for XML Transform Operations


When creating XML transformations, you should follow the general steps for manipulating documents that are described in the Using DFC in Documentum Applications manual.

40

Developing DFC Applications

Working With Documents

You must use the operations setSession method to specify a Docbase session. This operation requires a session, even if all of the files it operates on are on the file system. The add method of an IDfXMLTransformOperation object accepts Java types as well as Documentum types. It allows you to specify the file to transform as an object of any of the following types: IDfDocument IDfFile String (for example C:/PhoneInfo.xml) InputStream Reader URL

Handling Document Manipulation Errors


The examples in this chapter illustrate the ways that DFC reports errors that arise in the course of populating or executing operations.

The add Method Cannot Create a Node


The add method of any operation returns a null node if it cannot successfully add the document, file or folder that you pass it as an argument. Test for a null to detect and handle this failure. DFC does not report the reason for returning a null.

The execute Method Encounters Errors


The execute method of an operation throws DfException only in the case of a fatal error. Otherwise it creates a list of errors, which you can examine when the execute method returns or, if you use an operation monitor, as they occur.

Examining Errors After Execution


After you execute an operation, you can use its getErrors method to retrieve an IDfList object containing the errors. You must cast each to IDfOperationError to read its error message. After detecting that the operations execute method has returned errors, you can use the operations abort method to undo as much of the operation as it can. You cannot undo XML validation or transform operations, nor can you restore deleted objects.

Developing DFC Applications

41

Working With Documents

Examining Errors in an Operation Monitor


You can monitor the operation for progress and errors. Create a class that implements the IDfOperationMonitor interface and install it by calling IDfOperation.setOperationMonitor(). The operation periodically notifies the operation monitor of its progress or of errors that it encounters. During execution, DFC calls the methods of your Observer instance to report progress or errors. You can display this information to an end user. In each case DFC expects a response that tells it whether or not to continue. You can make this decision in the program or ask an end user to decide. Your Observer class must implement the following methods: progressReport DFC supplies the percentage of completion of the operation and of its current step. DFC expects a response that tells it whether to continue or to abort the operation. reportError DFC passes an object of type IDfOperationError representing the error it has encountered. It expects a response that tells it whether to continue or to abort the operation. getYesNoAnswer This is the same as reportError, except that DFC gives you more choices. DFC passes an object of type IDfOperationError representing the error it has encountered. It expects a response of yes, no, or abort. The Javadocs explain these methods and arguments in greater detail.
Example 214. Error handling /** * Handling Document Manipulation Errors: * Example 1 - Iterate through the list of errors generated during * specified operation. */ public DfException generateOperationException( IDfOperation operation, IDfSession session, String msg ) throws DfException { String message = msg; DfException e; try { String strNodeName = ""; String strNodeId = ""; String strSucceeded = ""; IDfId idNodesObj = null; // Get the list of errors IDfList errorList = operation.getErrors(); IDfOperationError error = null; IDfOperationNode node = null; // Iterate through errors and concat the error messages for( int i = 0; i < errorList.getCount(); ++i ) { error = (IDfOperationError)errorList.get( i );

42

Developing DFC Applications

Working With Documents

node = error.getNode(); idNodesObj = this.getObjectId( session, node ); if( null == idNodesObj ) continue; strNodeId = idNodesObj.getId(); strNodeName = session.apiGet( "get", strNodeId + ",object_name" ); message += "Node: [" + strNodeId + "], " + strNodeName + ", " + error.getMessage() + ", " + error.getException().toString(); } } catch( Exception err ) { message += err.toString(); } finally { // Create a DfException to report the errors e = new DfException(); e.setMessage( message ); } return e; }//end: generateOperationException(...) /** * Obtains the IDfId of the object represented by this node. * * IDfOperationNode publicly exposes a getId() method but * it only the id of the node, not the object_id of the * sysobject represented by the node. * * To obtain the object_id of the nodes sysobject, * you can write this method and then call it as follows: * * Assume you have obtained a node reference from other means * like, iterating through the operation errors, or op.getNodes() * list, etc... * * IDfId id = this.getObjectId( node ); * if( id == null ) * { // skip this node // * { * // use the id... * */ IDfId getObjectId( IDfSession session, IDfOperationNode node ) { try { return node instanceof IDfImportNode ? ((IDfImportNode)node).getObjectId() : node instanceof IDfExportNode ? ((IDfExportNode)node).getObjectId() : node instanceof IDfCheckoutNode ? ((IDfCheckoutNode)node).getObjectId() : node instanceof IDfCheckinNode ? ((IDfCheckinNode)node).getObjectId() : node instanceof IDfCancelCheckoutNode ? ((IDfCancelCheckoutNode)node).getObjectId() : node instanceof IDfDeleteNode ? ((IDfDeleteNode)node).getObjectId() : node instanceof IDfCopyNode ? ((IDfCopyNode)node).getObjectId()

Developing DFC Applications

43

Working With Documents

node instanceof IDfMoveNode ? ((IDfMoveNode)node).getObjectId() : null; } catch( Exception e ) { } return null; } // end: getObjectId() IDfId getNodesObjId( IDfOperationNode node ) { try { return node instanceof IDfImportNode ? ((IDfImportNode)node).getObjectId() : node instanceof IDfExportNode ? ((IDfExportNode)node).getObjectId() : node instanceof IDfCheckoutNode ? ((IDfCheckoutNode)node).getObjectId() : node instanceof IDfCheckinNode ? ((IDfCheckinNode)node).getObjectId() : node instanceof IDfCancelCheckoutNode ? ((IDfCancelCheckoutNode)node).getObjectId() : node instanceof IDfDeleteNode ? ((IDfDeleteNode)node).getObjectId() : node instanceof IDfCopyNode ? ((IDfCopyNode)node).getObjectId() : node instanceof IDfMoveNode ? ((IDfMoveNode)node).getObjectId() : null; } catch( Exception e ) { } return null; } // end: getObjectId() IDfSysObject getNodesSysObject( IDfSession session, IDfOperationNode node ) { try { IDfId idNodesObj = node instanceof IDfImportNode ? ((IDfImportNode)node).getObjectId() : node instanceof IDfExportNode ? ((IDfExportNode)node).getObjectId() : node instanceof IDfCheckoutNode ? ((IDfCheckoutNode)node).getObjectId() : node instanceof IDfCheckinNode ? ((IDfCheckinNode)node).getObjectId() : node instanceof IDfCancelCheckoutNode ? ((IDfCancelCheckoutNode)node).getObjectId() : node instanceof IDfDeleteNode ? ((IDfDeleteNode)node).getObjectId() : node instanceof IDfCopyNode ? ((IDfCopyNode)node).getObjectId() : node instanceof IDfMoveNode ? ((IDfMoveNode)node).getObjectId() : null; if( idNodesObj != null ) { return (IDfSysObject)session.getObject( idNodesObj ); } } catch( Exception e ) { } return null; }// end getNodesSysObject()

44

Developing DFC Applications

Working With Documents

Operations and Transactions


Operations do not use transactions, because operations Support distributed operations involving multiple docbases. May potentially process vast numbers of objects. Manage non-database resources such as the system registry and the local file system.

You can undo most operations by calling an operations abort method. The abort method is specific to each operation, but generally undoes Docbase actions and cleans up registry entries and local content files. Some operations (for example, delete) cannot be undone. If you know an operation only contains objects from a single Docbase, and the number of objects being processed is small enough to ensure sufficient database resources, you can wrap the operation execution in a transaction.

Developing DFC Applications

45

Working With Documents

46

Developing DFC Applications

Chapter 3 Working With Docbase Sessions


Introduction
As described in Client/Server Model, page 14, the IDfClient interface encapsulates communication between application programs and Documentum servers. Using methods of that interface, you can obtain sessions with Docbases. A session is an object that implements the IDfSession interface. A session gives you access to a specific Docbase.

Managed and Unmanaged Sessions


Prior to version 5, DFC supported only one kind of session. The current version of DFC supports two kinds of session: unmanaged (corresponding to the original DFC sessions) and managed. In general, you should use only managed sessions. You must use managed sessions with the Documentum business objects framework (BOF). This chapter describes the basics of working with Docbase sessions from DFC. Managing Sessions for Business Objects, page 121 provides additional information about using managed sessions. Acquiring a session with a Docbase requires authentication, that is, identifying yourself, so that the Documentum server can enforce the rules that control your access to each object in the Docbase. The process of authentication for managed sessions differs from the process for unmanaged sessions. This document deals primarily with managed sessions. For the specialized situations in which you might wish to use unmanaged sessions (for example, to maximize performance in an environment that does not use the Documentum servers session pooling capabilities). You can find documentation of how to use unmanaged sessions in the DFC 4.2.13 version of Using DFC in Documentum Applications (June 2002). Documentum continues to support unmanaged sessions to facilitate migration of existing applications to the current version of DFC. To further this end, DFC enables you to use managed and unmanaged sessions interchangeably, except for some paired methods. For example, if you acquire a managed session, you cannot use its disconnect method, because that method applies only to unmanaged sessions. A similar restriction applies to opening and ending transactions.

Developing DFC Applications

47

Working With Docbase Sessions

Session Manager
To use managed sessions, you must obtain a session manager, that is, an object that implements the IDfSessionManager interface. Use the newSessionManager method of IDfClient to obtain a session manager. The session manager you obtain is for your application only. You can destroy or abandon it when you are done with it. Once you have a session manager, you must provide it with the appropriate authentication information. You can do this in either of the following ways: Supply login credentials for each Docbase with which you expect the session manager to provide sessions. Supply a principal identity. A principal identity is a user account recognized by all Docbases with which you expect the session manager to provide sessions. In order to use this facility you must provide a mechanism to allow the named user account to authenticate itself with the session manager. Thereafter, the session manager uses its own highly privileged user account to establish sessions on the named accounts behalf. The IDfSessionManager interface provides methods and exception classes to enable you to: Acquire and release sessions Process transactions Authenticate users Temporarily prevent reassignment of sessions Obtain diagnostic data (statistics). Catch checked and unchecked exceptions.

Session Pool
The Documentum server provides a connection pooling capability to minimize the overhead of connecting and disconnecting sessions. The Server Fundamentals and Server Administration Guide manuals explain how connection pooling works and how to configure it. When you enable connection pooling, a session manager controls a pool of sessions to Docbases. In general, it maintains one session per Docbase, sharing that session among all callers that refer to that Docbase. When you release a session that the session manager gives you, it waits a specified interval before disconnecting it. If you request another session within that interval, you will in general get back the session you releasedwith negligible processing overhead. Transactions and multi-threading cause exceptions to this rule. The fact that obtaining and releasing sessions entails negligible processing overhead leads to the following best practice for working with managed sessions: Tip Ask the session manager for a session when you need one, and release the session back to the session manager as soon as you finish the Docbase interaction for which you obtained the session.

48

Developing DFC Applications

Working With Docbase Sessions

Using a Session Manager


This section provides details of how to use a session manager. Managing Sessions for Business Objects, page 121 provides additional information about using managed sessions.

Lifetimes of Sessions and Managers


The lifetime of a session manager object is under control of the client application. That is, a service must explicitly construct and destroy the session manager objects it uses. Once the client defines identities, the session manager manages sessions transparently, so the client typically never handles a DFC session directly. Documentum recommends against accessing sessions directly from client applications. The methods of an application request a DFC session from the session manager when they require Docbase access and release the DFC session quickly, usually upon returning from the method. The session manager keeps track of the requested sessions and only gives them back to the pool after the reference counter goes to zero. Once the client program no longer needs the session manager it can simply abandon it. For example, if an expiring HTTP session object contains a session manager, there is no need for explicit cleanup. However, the client program cannot abandon a session manager if doing so leads to any of the following unmatched session manager methods: beginClientControl with no matching endClientControl. beginTransaction with no matching commitTransaction or abortTransaction. getSession or newSession with no matching release.

When the Java garbage collector collects a session manager object, it checks for pending sessions and writes a message to the log file if it finds any. Once you release a session, you should not refer to persistent objects that you obtained from that session. This is true of both unmanaged and managed sessions. With unmanaged sessions, you catch this bug immediately, because the session disappears as soon as you disconnect it. With managed sessions, however, you can sometimes run into a hard to detect bug. Because the session manager does not immediately disconnect a session that you release, you can successfully refer to a persistent object attached to a released session for an indeterminate interval of time after you release the session. For example:
1 private void Method1( String DocbaseName, IDfId idDoc, 2 IDfSessionManager sMgr ) 3 { 4 IDfSession session = sMgr.getSession( strDocbaseName ); 5 IDfPersistenObject doc = session.getObject( idDoc ); 6 sMgr.release(session); 7 Method2( DocbaseName, doc ); 8 } 9 private void Method2( String DocbaseName, 10 IDfPersistentObject doc ) 11 { 12 String name = doc.getObjectName();

Developing DFC Applications

49

Working With Docbase Sessions

13 }

Sometimes line 12 works and sometimes it does not. During debugging, you can detect problems of this sort by setting the DebugSessionManager system property of the Java virtual machine.
java -D DebugSessionManager -classpath %classpath% YourProgram

This causes the session manager to disconnect the session as soon as you release it, or after a short interval even if you dont release it (to simulate server timeouts). Setting this property ensures that line 12 always fails.

Multiple Docbases
The session manager is able to manage connections to different Docbases transparently. For this behavior, the client application must register different identities (IDfLoginInfo / Docbase pairs) for the different Docbases, in which case the session manager uses the appropriate IDfLoginInfo object for each Docbase. The following example shows calling the same service for different Docbases:
IDfClient client = IDfSessionManager sMgr.setIdentity( sMgr.setIdentity( DfClient.getLocalClient(); sMgr = client.newSessionManager(); strDocbase1, loginInfo ); strDocbase2, loginInfo );

IMyService anyService = (IMyService) client.newService( IMyService.class.getName(), sMgr ); anyService.call(strDocbase1); anyService.call(strDocbase2);

The following example shows calling services in different Docbases using a principal:
IDfClient client = DfClient.getLocalClient(); IDfSessionManager sMgr = client.newSessionManager(); sMgr.setPrincipalName( principal ); IMyService anyService = (IMyService) client.newService( IMyService.class.getName(), sMgr); anyService.call(strDocbase1); anyService.call(strDocbase2);

AuthenticationSetting and Managing Identities


The Session Manager supports two different ways for it to connect to sessions on your behalf. The first, called manual identity, requires you to supply a IDfLoginInfo object for each Docbase you might connect to. The second connection mechanism, called a principal identity, allows the session manager to use a trusted user identity to act as a proxy. A principal identity is a user name that is

50

Developing DFC Applications

Working With Docbase Sessions

the same, and has the same password, in every Docbase you wish to connect to. You must provide an authentication mechanism to deliver the user name and password to the session manager. The session manager then acts on the principals behalf to obtain the necessary sessions. After you define identitiesmanual or principalyou pass only the Docbase name to the session manager. It handles authentication with the Docbase transparently.

Using Manual Identities


The following example shows how to set a manual identity:
IDfLoginInfo loginInfo = clientx.getLoginInfo(); loginInfo.setUser( user ); loginInfo.setPassword( password ); if( domain != null ) loginInfo.setDomain( domain ); IDfClient client = DfClient.getLocalClient(); IDfSessionManager sMgr = client.newSessionManager(); sMgr.setIdentity( strDocbase, loginInfo );

You can specify one identity per Docbase. Note: Consecutive calls to the setIdentity method specifying the same Docbase cause the method to throw DfServiceException. If you need to change the identity associated with a Docbase, call the clearIdentity method first. You can use the authenticate method of IDfSessionManager to authenticate an identity. In some cases, you may want to authenticate users immediately (for example, in a login dialog). In this case, you can call the authenticate method after you define the identity. The session manager tries to connect to the Docbase and throws DfAuthenticationException if the Docbase rejects the login information. For example:
IDfClient client = DfClient.getLocalClient(); IDfSessionManager sMgr = client.newSessionManager(); sMgr.setIdentity( strDocbase, loginInfo ); sMgr.authenticate( strDocbase );

Note: When using a session manager in a web application, protect security by using a separate session manager instance for each user session. Use the clearIdentity method to remove the identity for a Docbase or clearIdentities to remove the identities for all Docbases. To check for a specific user identity registered in the Session Manager for a given Docbase, use the hasIdentity method, or you can retrieve all the identities for a specified Docbase by using the getIdentities method. You can obtain a list of Docbases for which the session manager has identities by using the getDocbases method of IDfSessionManagerStatistics. You can obtain a

Developing DFC Applications

51

Working With Docbase Sessions

reference to an IDfSessionManagerStatistics object using the session managers getStatistics method:


IDfSessionManagerStatistics stats = sMgr.getStatistics(); Iterator list = stats.getIdentities( strDocbase ); IDfLoginInfo tempLogin; int count; for( count=0; list.hasNext(); ++count ) { tempLogin = (IDfLoginInfo)list.next(); } System.out.println( ""+count );

The following example demonstrates how to set a Docbase identity, call a method, and disconnect from that Docbase using the session manager:
void test() { IDfClient client = DfClient.getLocalClient(); IDfSessionManager sMgr = client.newSessionManager(); sMgr.setIdentity( strDocbase, loginInfo ); IMyService anyService = (IMyService) client.newService( IMyService.class.getName(), sMgr ); anyService.serviceMethod( strDocbase ); sMgr.clearIdentity( strDocbase ); }

Using Principal Identities


A principal identity is a trusted identity that the session manager can use to establish server sessions with any Docbase that the service will connect to. This requires a common user account name on all of those Docbases. The principal identity does not include a password, because the framework authenticates the identity. To implement the IDfPrincipalSupport interface, you must implement its single method, getSession. The getSession method takes two arguments, a Docbase name and a principal name, and returns an IDfSession reference. You must establish a new session from the Docbase and ensure that the mechanism protects the user account information of the superuser. When principal support is set and a client calls getSession, DFC invokes your getSession method. The following example shows an excerpt from a getSession method implemented in a subclass of DfPrincipalSupport. The principal support getSession method is called when principal support is set and a managed session is requested.
Figure 31. Implementing the getSession method of IDfPrincipalSupport 1 2 3 IDfSession sessionUser; String strTicket = sessionSuper.apiGet( "getlogin",

52

Developing DFC Applications

Working With Docbase Sessions

4 5 6 7 8 9 10 11 12 13 14 }

strPrincipalName ); IDfLoginInfo loginUser = new DfLoginInfo(); loginUser.setUser( strPrincipalName ); loginUser.setPassword( strTicket ); IDfSession sessionUser = client.getSession( strDocbaseName, loginUser ); return sessionUser; // good for about 5 minutes. (depending on // server settings you might not control)

DFC does not turn on principal support by default. To enable principal support, you must call the setPrincipalSupport method:
client.setPrincipalSupport ( new YourPrincipalSupport(loginSuper) );

When calling the setPrincipalSupport method, supply a reference to an active IDfLoginInfo of a superuser or system administrator. The principal support object can save this login information object in its memory:
IDfLoginInfo loginInfo = new DfLoginInfo(); loginInfo.setUser(superuser); loginInfo.setPassword(superuserPasswd); DfSessionManager sMgr = new DfSessionManager(); client.setPrincipalSupport(new SamplePrincipalSupport(loginInfo));

DFC uses principal support to generate a session for the principal. The principal service support interface IDfPrincipalSupport defines a method getSession that returns the DFC session for a given Docbase/principal combination. It is up to the implementation to obtain the trusted identity. Documentum provides a class, SamplePrincipalSupport, that implements the IDfPrincipalSupport interface. The constructor takes the login information of a user with sufficient permissions to generate login tickets for users. That user must have the same login credentials for all Docbases, and the service must obtain those credentials to get started. This class is for illustration purposes only. Documentum recommends that for production use you implement a class that meets all of your companys security criteria.

Developing DFC Applications

53

Working With Docbase Sessions

Figure 32. Principal Identity Diagram

Setting a Principal Identity The setPrincipalName method sets the principal name. The method takes the principal name as a string, not as a Principal object. Once you register a principal name, DFC uses it for all Docbases that you access. It is not possible to define a principal for a specific Docbase. Each call to setPrincipalName replaces the previous value. Pass null to reset the principal name. The following code shows how to set the principal name:
IDfClient client = DfClient.getLocalClient(); IDfSessionManager sMgr = client.newSessionManager(); sMgr.setPrincipalName( strPrincipalName );

Note: When you set both principal and manual identities, DFC uses the manual identity for user authentication. The getPrincipalName method returns the principal name, or null if no principal is defined.

54

Developing DFC Applications

Chapter 4 Managing Docbase Queries with DFC

This chapter describes the way to use DFC to create and perform queries and to process the results. The examples in it are based on the class DfExSimpleQuery, which is available in Java and Visual Basic versions on http://www.documentum.com/developer/samplecode.htm. You can find out more about queries by examining the DfExFullTextQuery class. This manual does not contain examples from that class.

Queries
DFC provides an easy-to-use mechanism for querying the Docbase and processing the query results. You use a query object to submit the query, and receive the results in a collection object.

Flow of Query Processing


The general flow of query processing is as follows.
To query the Docbase and process the results:

1. 2. 3.

Obtain an IDfClient interface by calling DfClient.getLocalClient. Create a session, sess, by calling newSession or getSharedSession on the IDfClient object. Obtain an IDfQuery object, q: For Java-based DFC programs, call new DfQuery. For Visual Basic and C++ programs, call the getQuery method of IDfClientX.

4. 5. 6.

Create a DQL query as a text string, dq. Call q.setDQL(dq) to set the DQL string into the query object. Call q.execute(sess, querytype) to execute the query.

The arguments of the execute method include a session reference, because the query is not tied to the session, and a code for the type of query to execute. The method returns an IDfCollection, col. The session remains locked until the execute method returns.

Developing DFC Applications

55

Managing Docbase Queries with DFC

7.

Iterate through the IDfCollection by calling col.next() until it returns False.

Obtain values from an IDfCollection by calling the various get methods of IDfTypedObject (the parent type of IDfCollection). For example, if you know that attribute 0 of the object at the current row of the collection is a string, the following code prints it:
IDfAttr attr = col.getAttr(0) System.out.println(typedObj.getString(attr.getName()))

If you dont know that the attribute is a string, you can find out what it is by calling
attr.getDataType()

and changing the second line above according to what getDataType returns. 8. Close the IDfCollection and IDfSession objects.

IDfQuery has no close method, because a query object is not tied to a session. Note: The number of sessions available to an application is limited. If you do not close them, you make it more likely that you will exhaust the supply. Be careful to close open collections and sessions even in the event of an exception. The best place for a Java program to call close is in a finally block, because Java executes a finally block whether there is an exception or not.

IDfQuery
An IDfQuery object holds a DQL query string and allows you to perform that query in any session. You pass the session and the query to the execute method, and it returns results as an IDfCollection object.

IDfCollection
An IDfCollection object is like an SQL cursor. It contains references to the objects that the query returns, in an ordered sequence of rows. The collection points to one row of data at a time. You must call next before accessing the first row (if the collection is empty, the first call to next returns False). Note: An IDfCollection is a typed object. You access the current rows data by calling the IDfTypedObject methods getBoolean, getInt, getString, and so forth, as if the collection were the same as its current row. You should not, and do not need, to call the collections getTypedObject method unless you want to save the current row for later use (compare the code in IDfCollection, page 56, which does not call getTypedObject, with the code in displayResults in Visual Basic, page 57, which does call getTypedObject).

56

Developing DFC Applications

Managing Docbase Queries with DFC

Basic Query Examples


execQuery in Visual Basic
Function execQuery( sess As IDfSession, queryString As String) As IDfCollection Dim clientx As New DfClientX Dim col As IDfCollection Dim q As IDfQuery On Error GoTo ErrorHandler Set execQuery = Nothing Set q = clientx.getQuery q.setDQL queryString Set col = q.execute(sess, DFCLib.IDfQuery_DF_READ_QUERY) Set execQuery = col Exit Function ErrorHandler: writeDiagnostic Err.Description, False End Function Session Query string Return a collection

Initialize return value Create query object Give it the query string Execute the query and get back a collection Set the return value

displayResults in Visual Basic


Step through a collection Sub displayResults(col As IDfCollection) Dim resItems As Integer Dim attr As IDfAttr Dim tObj As IDfTypedObject Dim msg As String On Error GoTo ErrorHandler resItems = 0 Count rows Step thru rows While (col.Next()) Set tObj = col.getTypedObject resItems = resItems + 1 Display row num writeDiagnostic "\nRow: " + CStr(resItems), False For i = 0 To (tObj.getAttrCount() - 1) For each attribute Set attr = tObj.GetAttr(i) Display name msg = attr.getName() + ": " If attr.getDataType = DFCLib.DF_BOOLEAN Then Display value writeDiagnostic msg + using method for its type CStr(tObj.getBoolean(attr.getName)), False ElseIf attr.getDataType = DFCLib.DF_DOUBLE Then writeDiagnostic msg + CStr(tObj.getDouble(attr.getName())), False ElseIf attr.getDataType = DFCLib.DF_ID Then writeDiagnostic msg + tObj.getId(attr.getName()).getId, False ElseIf attr.getDataType = DFCLib.DF_INTEGER Then writeDiagnostic msg + CStr(tObj.getInt(attr.getName())), False writeDiagnostic msg + tObj.getString(attr.getName()), False ElseIf attr.getDataType = DFCLib.DF_TIME Then writeDiagnostic msg + tObj.getTime(attr.getName()).toString(), False

Developing DFC Applications

57

Managing Docbase Queries with DFC

Else ERROR ACTION End If Next i Wend col.Close Exit Sub ErrorHandler: writeDiagnostic Err.Description, False End Sub

Unknown type Handle error

execQuery in Java
IDfCollection execQuery(IDfSession sess, String queryString) { IDfCollection col = null; //For the result try { IDfQuery q = new DfQuery(); //Create query object q.setDQL(queryString); //Give it the query col = q.execute(sess, DfQuery.DF_READ_QUERY); //Execute synchronously } catch (DfException dfe) { System.out.println("\n" + dfe.toString()); } return col; }

displayResults in Java
//Step through a collection and display results void displayResults(IDfCollection col) throws IOException { try { int resItems = 1; while (col.next()) { System.out.println("\nResult row: " + resItems++); for (int i = 0; i < col.getAttrCount(); i++) { IDfAttr attr = col.getAttr(i); System.out.print("\t" + attr.getName() + ": "); if (attr.getDataType() == attr.DM_BOOLEAN) { System.out.println( col.getBoolean(attr.getName())); } else if (attr.getDataType() == attr.DM_DOUBLE) { System.out.println( col.getDouble(attr.getName())); } else if (attr.getDataType() == attr.DM_ID) { System.out.println( col.getId(attr.getName()).toString()); } else if (attr.getDataType() == attr.DM_INTEGER) { System.out.println( col.getInt(attr.getName())); } else if (attr.getDataType() == attr.DM_STRING) { System.out.println( col.getString(attr.getName())); } else if (attr.getDataType() == attr.DM_TIME) { System.out.println( col.getTime(attr.getName()).toString()); } else { //ERROR ACTION

//Count rows //Display row num //For attribute // Display name // Display value // using method // for its type

//Unknown type // Handle error

58

Developing DFC Applications

Managing Docbase Queries with DFC

} } } col.close(); } catch (DfException dfe) { System.out.println("\n" + dfe.toString()); } }

//Close collection

Developing DFC Applications

59

Managing Docbase Queries with DFC

60

Developing DFC Applications

Chapter 5 Using Validation and ACLs

This chapter describes the way to work with Documentum features that help you automate your business rules. The examples in it are based on the classes DfExSimpleValidation andDfExACL, which are available in Java and Visual Basic versions at http://www.documentum.com/developer/ samplecode.htm. Documentum provides other ways to automate business rules (for example workflows and document lifecycles). The Documentum Content Server Fundamentals manual describes those facilities. This manual does not contain examples of using DFC to work with workflows and document lifecycles. This chapter contains the following main sections: Checking Objects Against Validation Rules, page 61 Changing Permissions, page 62 Using Private ACLs, page 64 ACL Utility Methods, page 65

Checking Objects Against Validation Rules


validate in Java
// Perform validation void validate( IDfSession sess, String objIdStr, String attrName) //Session //ID of the object to validate //Attribute to validate (null or "" = perform both // object level and attribute level validation) throws DfValidationException, IOException { try { IDfId objId = new DfId(objIdStr); IDfPersistentObject perObj = sess.getObject(objId); IDfValidator validator = perObj.getValidator(); IDfType type = perObj.getType(); if (attrName == null || attrName.equals("")) { validator.validateAll(null, false); } else { if (type.findTypeAttrIndex(attrName) < 0) { //ERROR ACTION return; }

Developing DFC Applications

61

Using Validation and ACLs

// validate the value of the specific attribute validator.validateAttrRules(attrName, null, null); } } catch (DfException dfe) { System.out.println("\n" + dfe.toString()); } }

Changing Permissions
changeBasicPermissions in Visual Basic
Change and display object permissions Sub changeBasicPermissions( sess As IDfSession, Session objId As String, ID of obj for which to change permissions anotherUser As String) A user to whom to assign permissions Dim clientx As New DfClientX Dim sysObjId As IDfId Dim sysObj As IDfSysObject Dim pObj As IDfPersistentObject On Error GoTo ErrorHandler Use ID string to obtain the ID, then the object Set sysObjId = clientx.getId(objId) Set sysObj = sess.GetObject(sysObjId) displayBasicPermissions sysObj Display the objects permissions sysObj.grant anotherUser, 6, "" Grant the user and dm_world sysObj.grant "dm_world", 6, "" WRITE permission Set pObj = sysObj Make the object persistent pObj.save then save it displayBasicPermissions sysObj Display the objects permission sysObj.revoke anotherUser, "" Revoke the users permissions sysObj.grant "dm_world", 3, "" Grant dm_world READ permission Set pObj = sysObj Make the object persistent pObj.save then save it displayBasicPermissions sysObj Display the objects permission Set sysObjId = Nothing Free memory Set sysObj = Nothing Exit Sub ErrorHandler: writeDiagnostic Err.Description, False End Sub

changeExtendedPermissions in Visual Basic


Change and display extended object permissions Sub changeExtendedPermissions( sess As IDfSession, Session objId As String, ID of obj for which to change permissions anotherUser As String) A user to whom to assign permissions Dim clientx As New DfClientX Dim sysObjId As IDfId Dim sysObj As IDfSysObject Dim pObj As IDfPersistentObject On Error GoTo ErrorHandler

62

Developing DFC Applications

Using Validation and ACLs

Use ID string to obtain the ID, then the object Set sysObjId = clientx.getId(objId) Set sysObj = sess.GetObject(sysObjId) displayExtendedPermissions sysObj sysObj.grant anotherUser, 6, "CHANGE_STATE" Set pObj = sysObj pObj.save displayExtendedPermissions sysObj sysObj.revoke anotherUser, "CHANGE_STATE" sysObj.revoke anotherUser, "" Set pObj = sysObj pObj.save displayExtendedPermissions sysObj Set sysObjId = Nothing Set sysObj = Nothing Exit Sub ErrorHandler: writeDiagnostic Err.Description, False End Sub

Display the ext Grant WRITE and Make the object then save it Display the ext

permissions CHANGE_STATE persistent permissions

Make the object persistent then save it Display the ext permissions Free memory

changeBasicPermissions in Java
//Change and display object permissions void changeBasicPermissions( IDfSession sess, //Session String objId, //ID of obj for which to change permissions String anotherUser) //A user to whom to assign permissions throws IOException { try { //Use ID string to obtain the ID, then the object IDfId sysObjId = new DfId(objId); IDfSysObject sysObj = (IDfSysObject)sess.getObject(sysObjId); displayBasicPermissions(sysObj); //Display the objects permissions //Grant the user and dm_world WRITE permission sysObj.grant( anotherUser, 6, ""); sysObj.grant("dm_world", 6, ""); sysObj.save(); //Save the object displayBasicPermissions(sysObj); //Display the objects permissions //Revoke the users permissions and grant dm_world READ permission sysObj.revoke(anotherUser, ""); sysObj.grant ("dm_world", 3, ""); sysObj.save(); //Save the object displayBasicPermissions(sysObj); //Display the objects permissions } catch (DfException dfe) { System.out.println("\n" + dfe.toString()); } }

changeExtendedPermissions in Java
//Change and display extended object permissions void changeExtendedPermissions( IDfSession sess, //Session String objId, //ID of obj for which to change permissions String anotherUser) //A user to whom to assign permissions throws IOException { try { //Use ID string to obtain the ID, then the object

Developing DFC Applications

63

Using Validation and ACLs

IDfId sysObjId = new DfId(objId); IDfSysObject sysObj = (IDfSysObject)sess.getObject(sysObjId); displayExtendedPermissions(sysObj); //Display the ext permissions //Grant the user WRITE and CHANGE_STATE permissions sysObj.grant(anotherUser, 6, "CHANGE_STATE"); sysObj.save(); displayExtendedPermissions(sysObj); sysObj.revoke(anotherUser, "CHANGE_STATE"); sysObj.revoke(anotherUser, ""); sysObj.save(); displayBasicPermissions(sysObj); } catch (DfException dfe) { System.out.println("\n" + dfe.toString()); } } //Save the object //Display the ext permissions //Revoke users CHANGE_STATE //Revoke users basic perms //Save the object //Display the ext permissions

Using Private ACLs


privateACLs in Visual Basic
Create a private ACL and apply it to an object Sub privateACLs( sess As IDfSession, Session objId As String, Object with which to associate the ACL permission As String, Permission to grant world and owner extPermission As String, Ext permissions to grant world and owner aclName As String) Name of ACL to create Dim clientx As New DfClientX Dim sysObjId As IDfId Dim sysObj As IDfSysObject Dim pObj As IDfPersistentObject Dim oldACL As IDfACL Dim newACL As IDfACL On Error GoTo ErrorHandler Use ID string to obtain the ID, then the object Set sysObjId = clientx.getId(objId) Set sysObj = sess.GetObject(sysObjId) Create a new ACL object and give it the specified name Set pObj = sess.newObject("dm_acl") pObj.apiSet "set", "object_name", aclName Grant the specifiedpermissions to owner and world pObj.apiExec "grant", "dm_owner," + permission + "," + extPermission pObj.apiExec "grant", "dm_world," + permission + "," + extPermission pObj.save Save the new private ACL Set oldACL = sysObj.getACL Save the objects current ACL Instantiate an instance of the new private ACL Set newACL = sess.getACL(sess.getLoginUserName(), aclName) sysObj.setACL newACL Apply new ACL to the sysobject Set pObj = sysObj Use persistent obj interface to pObj.save save it with its new ACL displayBasicPermissions sysObj Display the new permissions displayExtendedPermissions sysObj sysObj.setACL oldACL Apply old ACL to the sysobject pObj.save Save it (pObj & sysObj are the same) displayBasicPermissions sysObj Display restored permissions displayExtendedPermissions sysObj Set sysObj = Nothing Free memory Set sysObjId = Nothing

64

Developing DFC Applications

Using Validation and ACLs

Set oldACL = Nothing Set newACL = Nothing Exit Sub ErrorHandler: writeDiagnostic Err.Description, False End Sub

privateACLs in Java
//Create a private ACL and apply it to an object void privateACLs( IDfSession sess, //Session String objId //Object with which to associate the ACL String permission, //Permission to grant to world and owner String extPermission, //Ext permissions to grant world and owner String aclName //Name of ACL to create ) throws IOException { try { //Use ID string to obtain the ID, then the object IDfId sysObjId = new DfId(objId); IDfSysObject sysObj = (IDfSysObject)sess.getObject(sysObjId); //Create a new ACL object and give it the specified name IDfPersistentObject pObj = (IDfPersistentObject)sess.newObject("dm_acl"); pObj.apiSet("set", "object_name", aclName); //Grant the specified permissions to owner and world pObj.apiExec("grant", "dm_owner," + permission + "," + extPermission); pObj.apiExec("grant", "dm_world," + permission + "," + extPermission); pObj.save(); //Save the new private ACL IDfACL oldACL = sysObj.getACL(); //Save the objects current ACL // Instantiate an instance of the new private ACL IDfACL newACL = sess.getACL(sess.getLoginUserName(), aclName); sysObj.setACL(newACL); //Apply new ACL to the sysobject sysObj.save(); //Save sysobject with its new ACL displayBasicPermissions(sysObj); //Display new permissions displayExtendedPermissions(sysObj); sysObj.setACL(oldACL); //Apply old ACL to the sysobject sysObj.save(); //Save sysobj with restored ACL displayBasicPermissions(sysObj); //Display restored permissions displayExtendedPermissions(sysObj); } catch (DfException dfe) { System.out.println("\n" + dfe.toString()); } }

ACL Utility Methods


permissionToString in Visual Basic
Convert permission code to name Function permissionToString(permission As String) As On Error GoTo ErrorHandler If permission = "1" Then permissionToString = ElseIf permission = "2" Then permissionToString = ElseIf permission = "3" Then permissionToString = ElseIf permission = "4" Then permissionToString = ElseIf permission = "5" Then permissionToString = String "NONE" "BROWSE" "READ" "NOTE" "VERSION"

Developing DFC Applications

65

Using Validation and ACLs

ElseIf permission = "6" Then permissionToString = "WRITE" ElseIf permission = "7" Then permissionToString = "DELETE" End If Exit Function ErrorHandler: writeDiagnostic Err.Description, False End Function

extendedPermissionToString in Visual Basic


Convert extended permission code to name Function extendedPermissionToString(permission As String) As String On Error GoTo ErrorHandler If ElseIf ElseIf ElseIf ElseIf End If permission permission permission permission permission = = = = = "1" "2" "3" "4" "5" Then Then Then Then Then extendedPermissionToString extendedPermissionToString extendedPermissionToString extendedPermissionToString extendedPermissionToString = = = = = "CHANGE_STATE" "CHANGE_PERMIT" "CHANGE_OWNER" "EXECUTE_PROC" "CHANGE_LOCATION"

Exit Function ErrorHandler: writeDiagnostic Err.Description, False End Function

displayBasicPermissions in Visual Basic


Display object permissions Sub displayBasicPermissions(sysObj As IDfSysObject) On Error GoTo ErrorHandler writeDiagnostic " ACL Name: " + sysObj.getACLName, False ACL name For i = 0 To (sysObj.getAccessorCount - 1) For each accessor writeDiagnostic " Accessor: " + Name sysObj.getAccessorName(i) + " Permission: " + Permission permissionToString(sysObj.getAccessorPermit(i)), False Next i Exit Sub ErrorHandler: writeDiagnostic Err.Description, False End Sub

displayExtendedPermissions in Visual Basic


Display the objects extended permissions Sub displayExtendedPermissions(sysObj As IDfSysObject) On Error GoTo ErrorHandler

66

Developing DFC Applications

Using Validation and ACLs

writeDiagnostic " ACL Name: " + sysObj.getACLName, False For i = 0 To (sysObj.getAccessorCount - 1) writeDiagnostic " Accessor: " + sysObj.getAccessorName(i) + " Extended Permissions: " + sysObj.getAccessorXPermitNames(i), False Next i Exit Sub ErrorHandler: writeDiagnostic Err.Description, False End Sub

ACL name For each accessor Name Extended permissions

permissionToString in Java
//Convert permission code to name String permissionToString(String permission) { String retVal = null; if (permission.equals("1")) retVal = else if (permission.equals("2")) retVal = else if (permission.equals("3")) retVal = else if (permission.equals("4")) retVal = else if (permission.equals("5")) retVal = else if (permission.equals("6")) retVal = else if (permission.equals("7")) retVal = return retVal; }

"NONE"; "BROWSE"; "READ"; "NOTE"; "VERSION"; "WRITE"; "DELETE";

extendedPermissionToString in Java
//Convert extended permission code to name String extendedPermissionToString(String permission) { String retVal = null; if (permission.equals("1")) retVal = "CHANGE_STATE"; else if (permission.equals("2")) retVal = "CHANGE_PERMIT"; else if (permission.equals("3")) retVal = "CHANGE_OWNER"; else if (permission.equals("4")) retVal = "EXECUTE_PROC"; else if (permission.equals("5")) retVal = "CHANGE_LOCATION"; return retVal; }

displayBasicPermissions in Java
//Display object permissions void displayBasicPermissions(IDfSysObject sysObj) { try { System.out.println( "\tACL Name: " + sysObj.getACLName());

//ACL name

Developing DFC Applications

67

Using Validation and ACLs

for (int i = 0; i < sysObj.getAccessorCount(); i++) { //For each accessor System.out.println( "\tAccessor: " + //Name sysObj.getAccessorName(i) + " Permission: " + //Permission permissionToString(sysObj.getAccessorPermit(i))); } } catch (DfException dfe) { System.out.println("\n" + dfe.toString()); } }

displayExtendedPermissions in Java
//Display the objects extended permissions void displayExtendedPermissions(IDfSysObject sysObj) { try { System.out.println( "\tACL Name: " + sysObj.getACLName()); for (int i = 0; i < sysObj.getAccessorCount(); i++) { System.out.println( "\tAccessor: " + sysObj.getAccessorName(i) + " Extended Permissions: " + sysObj.getAccessorXPermitNames(i)); } } catch (DfException dfe) { System.out.println("\n" + dfe.toString()); } }

//ACL name //For each accessor // // Name Ext permissions

68

Developing DFC Applications

Chapter 6 Understanding Business Objects

The Documentum business objects framework (BOF) provides a framework and a methodology for developing reusable middleware server components, called business objects, to embody and enforce business logic. This chapter introduces business objects and the benefits they provide. It contains the following major sections: Introduction to Business Objects, page 69 Service Based Business Objects, page 77 Type Based Business Objects, page 83 Documentum Business Object Registry (DBOR), page 89

Introduction to Business Objects


Overview of BOF
BOF provides an object oriented framework for building, testing, discovering, and deploying server business logic as business objects. It provides a way for developers to hook their logic into DFC by extending DFC classes. BOF consists of several DFC classes and interfaces for constructing and running business objects. It lives wherever DFC lives: on the Documentum server, an application server, or any other host for programs that access Documentum functionality. A typical Documentum application has a multi-tiered structure, usually consisting of the following tiers, or code layers: Presentation The presentation layer consists displays content and structured information to users and accepts input from them. It runs in a web browser or stand alone application. Visual Basic, Java Swing, or Documentums WDK can implement the presentation layer, using commercial or custom UI components that display information in different ways, depending on factors like users roles or privileges. The presentation layer relies on the components (business objects) of the business logic layer to implement and enforce the rules and policies of the company. Business logic

Developing DFC Applications

69

Understanding Business Objects

The business logic layer implements customer specific rules and policies. These usually change infrequently, so it makes sense to separate them from code that changes more frequently. If they do change, their central location in the business logic layer ensures that dependent applications and components automatically conform to the new policy. The business logic layer is the focus of BOF. You can implement the business logic and leave session management and transaction handling to DFC. Data The data layer stores objects, content, and other information. It uses one or more content servers, with their associated relational database servers. The data layer has the following logical sublayers: Content and data schema The object hierarchy and physical schema used to store business data. The business logic layer provides an abstraction of the details of the DFC interfaces to the content and data schema. Business objects manipulate content and its metadata on behalf of the presentation layer, thereby isolating presentation logic from storage details. This leads to portable, scalable applications. Core content management services Documentum Content Server provides library services, process automation, and content authentication to the business logic layer.
Figure 61. Documentum Business Objects N-Tier Model

BOFs business objects are of the following types: Type based objects (TBOs) A TBO corresponds to a subtype of a Documentum persistent type, usually dm_document. Its DFC implementation extends the implementation class for the

70

Developing DFC Applications

Understanding Business Objects

base type. For example, com_accelera_catalog might extend dm_document and enforce its business logic by overriding methods (for example, save, checkinEx and checkoutEx) of the DFC class DfDocument. Create a TBO to provide new behavior for custom object types (for example, get or set custom attributes) or to override Documentums standard behavior (for example, override the save and checkinEx methods to enforce data validations, referential integrity and object specific business rules). Service based objects (SBOs) An SBO provides methods that are not necessarily bound to a specific object type or repository and can operate on different Documentum object types or other business objects. For example, the Documentum IInbox service manages an inbox. Use public BOF interfaces and DFC implementation classes and factory methods to build SBOs. BOF enables you (or Documentum, or a third party) to develop pluggable components, implementing middle-tier business rules. Figure 62, page 71 shows how BOF relates to the rest of DFC. Notice that the DFC core layer implements most of BOF.
Figure 62. BOF is integral to DFC

Benefits of Using BOF


The Documentum business object framework (BOF) enables you to develop business logic rapidly and to protect your investment by making reusable components that interoperate with existing software. Business objects ensure data integrity by centralizing business logic in the server. They leverage the capabilities of application servers, and web services, and they help you enforce best practices and standards. Because BOF builds on DFC, you can implement business objects without a steep learning curve and can maintain compatibility with existing DFC applications.

Developing DFC Applications

71

Understanding Business Objects

Use business objects to implement business logic that is: Object oriented, modular, and reusable Compatible with existing DFC code Independent of presentation

BOF Architecture
BOF provides an environment for stateless access to Docbase data from middle-tier business objects that implement business rules. Using BOF, you can write content management services that other applications begin to use automatically. You dont need to modify existing applications to ensure that they follow the business rules you embody in your business objects. Business objects can use other business objects and benefit from their implementation of other business rules. The aspects of DFC that provide business object support are compatible with existing applications. Because BOF is part of DFC, everyone accesses business objects the same way. The DFC core integrates the object factory and object registry. It also manages sessions, transactions, and user authentication. This section describes the elements of DFC that support BOF. It contains the following main subsections: Object Factory, page 72 Accessing Business Objects, page 73 Session Manager, page 75 Documentum Business Objects Registry (DBOR), page 76 Business Objects Class Hierarchy, page 76

Object Factory
The object factory constructs type based objects (TBOs) at runtime. You define TBOs to extend Docbase types (for example, dm_document), and you define their behavior by extending the corresponding DFC classes (for example, DfDocument). When you develop and deploy a TBO on your system, the framework guarantees that all software accessing this object through previous means now obtains the new extended object. For example, when a servlet uses the session.getObjectByQualification method, DFC fetches the object from the Docbase. If the FROM clause of the associated query specifies dm_sysobject, but the WHERE clause indicates instances of the TBO, the method returns an instance of your extension of DfSysObject. This happens even when the servlet accesses the Docbase with code written before you defined the TBO. When the servlet calls methods like checkout and save, and the TBO overrides these methods (for example, to add validation logic to the save method, DFC invokes the overridden methods. The object factory depends on the Documentum business objects registry (DBOR). When you create a TBO, you must register it with DBOR. Whenever you use DFC to instantiate a custom type, DFC asks DBOR if the type has an associated Java class. If so, DFC loads

72

Developing DFC Applications

Understanding Business Objects

and instantiates that class. Documentum Business Objects Registry (DBOR), page 76 provides more details about DBOR. Figure 63, page 73 shows getting access to a Docbase object through a TBO after DFC has checked with DBOR to find the Java class to construct to represent the TBO.
Figure 63. TBO Interaction Diagram

Accessing Business Objects


This section discusses aspects of accessing business objects.

Accessing TBOs
Figure 64, page 73 shows a type based business object (TBO) becoming the client of another TBO.
Figure 64. Business Object Using Another Business Object

Developing DFC Applications

73

Understanding Business Objects

Accessing SBOs
Figure 65, page 74 shows how an SBO differs from the TBOs shown in Figure 63, page 73. Each SBO provides an interface to a group of related operations. The IDfClient interface provides a factory for SBOs. The IDfClient method checks DBOR for the service name and instantiates its associated Java class. SBOs can access objects across several Docbases. You can implement an SBO so that an application server component can call and the SBO, and the SBO can obtain and release Docbase sessions dynamically as needed.
Figure 65. SBO Interaction Diagram

Calling a Service based Object


Any DFC based application can call a method of a business object. A WDK component can call an SBO service just as easily as any standalone Java program can. JSP, ASP, Visual Basic, and other languages all have access to business objects.

Calling a Business Object From Another Business Object


When you use a business object, the object factory methods use DBOR to identify the implementing Java class and load it into the process address space of the JVM. When an SBO calls another SBO or another TBO, the interaction between the clients, DBOR, and the implementing classes proceeds the same way as when a standalone program makes the call. When a TBO calls an SBO or another TBO, DFC treats the caller like the client in Figure 63, page 73. Figure 66, page 75 shows a service based business object calling another service based business object.

74

Developing DFC Applications

Understanding Business Objects

Figure 66. Any Business Object calling an SBO

Executing Business Objects Remotely


Documentum business objects do not support remote execution.

Using Business Objects From Non-Java Clients


You can develop business objects only in Java, but you can access them from a variety of clients, including Java, WDK, Servlets, JSP, Visual Basic, C++, and ASP. Non-Java clients access business objects via Documentums Java COM Bridge.

Session Manager
DFC provides more than one way to establish sessions with Documentum servers. When accessing business objects, however, always use the DFC session manager. This facility manages resources so that you dont have to. You can (and should) acquire sessions when you need them and release them as soon as you are finished with the immediate task. If you subsequently open another session, DFC avoids the session handling overhead by invisibly managing the session pool. It also provides several ways to handle authentication, including principal identity support to enable you to implement a single login for multiple Docbases. It also provides support for transactions that can involve more than one Docbase. For web programmers, it also provides methods to associate state with the session to make session management more straightforward. An SBO should request a DFC session through the session manager and release it as soon as it no longer needs to access a Docbase. A TBO has a reference to its session as a data member. That reference can become invalid if the requesting method releases the pooled session. You can explicitly separate the TBO from the current DFC session and put the TBO under control of the session manager. This is required in cases where a stateless SBO creates a TBO, which is stateful, to return to the caller. The session manager provides a transaction facility that supports acquiring and releasing sessions quickly. For example, a program might call upon two business objects, one to create folders and a second to place files in them. Placing these two calls into a

Developing DFC Applications

75

Understanding Business Objects

transaction ensures that the entire operation, not just the individual operations, becomes atomic. DFC accomplishes this invisibly, even though each business object might use a different physical session. DFC sessions use a single-phase commit, because the underlying relational databases do not support two-phase commits. The Using DFC manual provides details of using the session manager.

Documentum Business Objects Registry (DBOR)


When a DFC method must return a reference to a new object, it must determine the proper Java class to instantiate. One step in making this determination is checking to see whether the requested object corresponds to a TBO or SBO registered in DBOR. If you create a business object, you must register it with DBOR by providing one of the following mappings: TBO name (for example, com_accelera_catalog) to implementing Java class. SBO Interface name (for example, com.documentum.IInbox) to implementing Java class.

At runtime, DBOR provides the appropriate class name to the DFC method, which loads and instantiates the Java class and returns the reference.

Business Objects Class Hierarchy


Figure 67, page 77 shows a class diagram for a service based business object. The Client object represents the consumer of the IAutoNumber service. The IAutoNumber service interface is implemented by the AutoNumber class. The IAutoNumber service interface has access to the DfService object extended by its AutoNumber implementation. The client gains access to the IAutoNumber service by using IDfClient to find the class mapping from the IDfDbor, and then instantiates the AutoNumber object.

76

Developing DFC Applications

Understanding Business Objects

Figure 67. Class Diagram for Service based Business Objects

Figure 68, page 77 show a class diagram for a type based business object. The custom Product class extends the DFC DfSysObject class. The IProduct interface generalizes access to the Product object. The client gains access to the Product object by using the getObject, method of IDfSession, which causes the IDfClient of the framework to query DBOR registry for the class to instantiate.
Figure 68. Class Diagram for Type-based Business Objects

Service Based Business Objects


Service based objects (SBOs) are components that are not bound to a specific Docbase object type. They can operate on multiple object types, retrieve objects types unrelated to Documentum objects (for example, external email messages), and perform processing.

Developing DFC Applications

77

Understanding Business Objects

An example of an SBO is a Documentum Inbox object. It retrieves items from a users inbox and performs operations like removing and forwarding items. SBOs are similar to session beans in an Enterprise Java Beans (EJB) environment. TBOs are more like entity beans. This chapter contains the following main sections: Architecture, page 78 Rules and Guidelines, page 79

Architecture
This section describes the design time and runtime aspects of SBO architecture.

Design Time
To create an SBO, extend the com.documentum.fc.client.DfService class and implement its corresponding IDfService interface. DfService is an abstract class that implements some common methods for services. The service interface IDfService and service abstract class DfService define the following methods: getName returns a logical service name The default implementation in DfService returns the fully qualified interface name (for example, com.documentum.services.inbox.IInbox). getVersion returns the current version of the service as a string The version is a string and must match the pattern: majorVersion.minorVersion (for example, "1.0"). The method getVersion is an abstract method of the DfService class. Each service implementation must override it. getVendorString returns a stringnormally the vendors copyright statement (for example, "Copyright 1994-2002 Documentum, Inc. All rights reserved.") isCompatible checks whether the class is compatible with a specified service version This allows you to upgrade service implementations without breaking existing code. Java does not support multiple versions of interfaces. supportsFeature checks whether the class supports a specified feature. The default implementation in DfService always returns false. getSessionManager returns the services session manager handle getSession returns a DFC session object Each time you call getSession, you must subsequently call releaseSession. The default implementation in DfSession calls the session manager to return a DFC session for the given Docbase name.

78

Developing DFC Applications

Understanding Business Objects

releaseSession releases a session that you obtained with getSession. cleanupResources releases the specified resources without waiting for the Java garbage collector to do so. The default implementation does nothing.

Runtime
An SBO client application uses the newService factory method of IDfClient to instantiate a service:
public IDfService newService( String name, IDfSessionManager sMgr ) throws DfServiceException;

The factory takes the service name and a session manager as parameters, and returns the service interface, which you must downcast to the specific service interface. The newService method uses the service name to look up the Java implementation class in DBOR. It stores the session manager as a member of the service, so that the service implementation can access the session manager when it needs a DFC session. Before you create a service, you must use the newSessionManager method of IDfClient to construct an IDfSessionManager object to use as a session handle for all services.

Rules and Guidelines


This section provides rules and guidelines for implementing and invoking SBOs.

Implementing Service Based Business Objects


This section provides rules and guidelines for implementing SBOs.

Naming Conventions
BOF does not impose constraints on service names. However, names must be unique within a DBOR, so Documentum recommends that you use the fully qualified service interface name as the service name. This prevents naming conflicts and is more convenient for calling the factory methods. The following code shows how you can simply pass the class name to the factory method if you use the interface name as the service name:
IAutoNumber autonumber = (IAutoNumber)client.newService( IAutoNumber.class.getName(), sMgr);

Developing DFC Applications

79

Understanding Business Objects

Java Classes As Parameters


Where possible, avoid using Java system classes as method parameters or return values, because such parameters make it hard to port the SBO to a non-Java environment like Microsofts COM. The DFC common package provides Java interfaces and classes that you can use as replacements for some Java system classes: IDfList/DfList in place of java.util.Vector. IDfProperties/DfProperties in place of java.util.Hashtable IDfTime/DfTime in place of java.util.Date

Remember that the Java COM Bridge supports the IDispatch interface for COM programs.

Stateful and Stateless SBOs


SBOs can maintain state between calls, but they are easier to deploy to multithreaded and other environments if they do not have to do so. For example, a checkin service needs parameters like retainLock and versionLabels. A stateful interface for such a service provides get and set methods for such parameters. A stateless interface makes you pass the state as calling arguments. The following sample interfaces for a checkin service illustrate these approaches:
//Stateful checkin service interface ICheckin extends DfService { public void setRetainLock( boolean retainLock ); public void setVersionLabels( String newVersionLabels ); . . . public void checkin( IDfSysObject object ) throws DfServiceException; . . . } //Stateless checkin service interface ICheckin extends DfService { public void checkin( IDfSysObject object, boolean retainLock, String newVersionLabels, . . .) throws DfServiceException; . . . } //Stateless checkin service with a configuration object interface ICheckin extends DfService { public ICheckinConfig newConfig (); public void checkin( IDfSysObject object, ICheckinConfig config ) throws DfServiceException; . . . }

80

Developing DFC Applications

Understanding Business Objects

Notice how the third example combines the stateless approach with the convenience of the first example. An ICheckinConfig object holds all parameters required for checkin and provides methods to get and set them. This is a convenient way to design a stateless interface when the calling program must provide more than a few parameters to the service.

Overriding Abstract Methods of DfService


SBOs extend the DfService class. They implement the following abstract methods that DfService defines: getVersion getVendorString isCompatible

Specifying the Docbase


In order acquire a DFC session, a method of the SBO needs to know the Docbase to use. The service can maintain this information between calls, but to make the service stateless, you must require callers to pass the Docbase to each method. If the service need not access more than one Docbase, and if it is not important for the service to be stateless, the service can declare a String member for the Docbase name and a method to set it, as in the following example:
private String m_strDocbase = null; public void setDocbase( String strDocbase ) { m_strDocbase = strDocbase; }

In most cases, however, you cant anticipate the environments in which your service will be used, so it is a good practice to make the Docbase name a parameter of every method.

Caching Docbase Data


DFC caches persistent Docbase data. There is no convenient way to keep a private cache synchronized with the DFC cache, so it is a good practice to rely on the DFC cache, rather than implementing a separate cache as part of your services implementation.

Structuring Methods to Use Sessions


You must define methods to implement the services functionality. One important aspect of doing so is handling Docbase sessions. Each method that obtains a session must release it when it is finished accessing the Docbase. It is important to ensure that you release the session, even if the method exits because of an exception. The following example shows how to structure a method to ensure that it releases its session:
public void doSomething( String strDocbase, . . . ) { IDfSession session = getSession( strDocbase );

Developing DFC Applications

81

Understanding Business Objects

try { // do something } catch( Exception e ) { // handle error } finally { releaseSession( session ); } }

Calling a Service Based Business Object


The client application should instantiate a new SBO each time it needs one, rather than reusing one. For example, to call a service during an HTTP request in a web application, instantiate the service, execute the appropriate methods, then abandon the service object. This approach is thread-safe, and it is efficient, because it requires little resource overhead. The required steps to instantiate a service are: 1. 2. 3. Prepare an IDfLoginInfo object containing the necessary login information. Instantiate a session manager object. Call the service factory method.

The following code illustrates these steps:


IDfClient client = DfClient.getLocalClient(); IDfLoginInfo loginInfo = new DfLoginInfo(); loginInfo.setUser( use r); loginInfo.setPassword( password ); if( domain != null ) loginInfo.setDomain(domain); IDfSessionManager sMgr = client.newSessionManager(); sMgr.setIdentity( strDocbase, loginInfo ); IAutoNumber autonumber = (IAutoNumber) client.newService( IAutoNumber.class.getName(), sMgr);

The session factory method may throw an exception to indicate one of the following problems: DfDborNotFoundException DFC cannot find DBOR. DfServiceNotFoundException DFC found DBOR, but it did not find the specified service. DfServiceInstantiationException

82

Developing DFC Applications

Understanding Business Objects

DFC found the service in DBOR, but it could not instantiate the specified Java class. This may happen if the Java class is not in the CLASSPATH or is an invalid data class. Security for Java classes on an application server may also cause this exception.

Type Based Business Objects


Introduction
Type based business objects (TBOs) are extensions of basic DFC types, such as IDfPersitentObject, IDfSysObject, IDfDocument, IDfFolder, or any other class that extends IDfPersistentObject. They can encapsulate business logic that is specific to a given object type. The main reasons for creating a TBO are to: Provide a new behavior for existing or new object types For example, you can add new get and set methods for object specific attributes, or create new methods, such as addProduct for a Catalog TBO. Customize low level operations to enforce data validations, referential integrity and object specific business rules For example, you can override the save and checkin methods to validate attributes before storing them in the repository. This section contains the following main subsections: Architecture, page 83 Implementation Rules, Guidelines, and Examples, page 85 Calling Rules, Guidelines, and Examples, page 88

Architecture
TBOs allow you to create and enforce business rules for custom Docbase types. For this to succeed, all programs that access Docbase objects of the given type must use the methods that implement those rules. Whenever a program calls methods like newObject or getObject, DFC performs the following steps: Determine the objects Docbase type, and fetch that object along with its supertype parts. Check DBOR for a mapping between the custom type and a Java class. If such a mapping exists, instantiate the Java class, and return it to the caller. You need not downcast to the subtype to use overridden methods of IDfPersistentObject (for example, getObjectId, getString, or save), but you must downcast to the interface of the new subtype in order to call any new methods (or methods of subclasses of IDfPersistentObject). If no such mapping exists, instantiate and return the standard DFC class (for example, DfDocument).

Developing DFC Applications

83

Understanding Business Objects

Caution DFC does not perform the preceding steps if you use UPDATE queries to modify the attributes of a TBO. Thus, using UPDATE queries circumvents the business logic that the TBO implements and can lead to inconsistencies and errors. The following code samples all retrieve the same com_accelera_autonumber Docbase object and execute the code in the overridden checkout method of AutoNumberType (see ).
String strDQL = "com_accelera_autonumber where r_object_id = 091a64c18001b382"; IDfDocument number = (IDfDocument) session.getObjectByQualification( strDQL ); number.checkout(); String strDQL = "dm_document where r_object_id = 091a64c18001b382"; IDfDocument number = (IDfDocument) session.getObjectByQualification( strDQL ); number.checkout(); String strDQL = "dm_document where r_object_id = 091a64c18001b382"; IAutoNumberType number = (IAutoNumberType) session.getObjectByQualification( strDQL ); number.checkout();

Object Factory
Use the standard DFC factory methods to construct an instance of a TBO. For example,
ICatalog catalog = (ICatalog)session.newObject( "catalog" ); ICatalog catalog = (ICatalog)session.getObject( idDoc );

The session.newObject method constructs an instance of the Java class for the TBO. The factory method checks DBOR to determine which Java class to instantiate (see Documentum Business Object Registry (DBOR), page 89). For example, DBOR might map the catalog type to the com.documentum.catalog. Catalog Java class, which implements the ICatalog interface. The client application can use this interface to handle and control a catalog object. DBOR may contain multiple entries for a type. This can happen when different applications handle the same object type differently. For this reason, the IDfSession interface provides factory methods that take the interface that represents the desired behavior as an argument. For example,
ICatalog2 catalog = (ICatalog2)s.getObjectWithInterface( idDoc, ICatalog2.class.getName() );

84

Developing DFC Applications

Understanding Business Objects

String strDql = "dm_document where r_object_id = " + idDoc.getId() + ""; ICatalog2 catalog = (ICatalog2)s.getObjectByQualificationWithInterface( strDql, ICatalog2.class.getName() );

These methods look up the interface name in DBOR and instantiate the appropriate Java class. Documentum Business Object Registry (DBOR), page 89 explains how to register and access alternate implementations for a TBO.

Implementation Rules, Guidelines, and Examples


When you design a TBO, you can Create new methods (for example, to get or set custom attributes or to provide new functionality) Override inherited methods (for example, to validate attributes or to implement abstract methods) To validate an individual attribute (for example, minRange is less than maxRange), you might override setString, appendString, or setRepeatingString to add validation code. To validate a combination of attributes, you probably need to override methods that store the object in the repository, such as save or checkinEx. Use the following points as a checklist when developing TBOs: Define an interface (for example, IAutoNumberType) to the TBO by extending IDfBusinessObject by adding the methods that you recommend programmers use to access objects of this type. Documentum recommends against defining the types interface to extend the interface of its corresponding Docbase supertype (for example, IDfDocument). If you expect programmers to call checkin and checkout on the object directly, for example, define those methods explicitly in the interface. Create a Java class to implement the type Extend the DFC superclass that matches the Docbase supertype, and implement the matching interface of that new class.
public class AutoNumberType extends DfDocument implements IAutoNumberType { }

Implement the abstract methods of the IDfBusinessObject class: getVersion, getVendorString, isCompatible, supportsFeature.

Developing DFC Applications

85

Understanding Business Objects

Table 61. IDfBusinessObject Methods to Implement IDfBusinessObject methods getVersion Description Return a constant String that describes the version (for example, "1.0") of the Java class for this object type. Return a constant String that provides copyright information (for example, "Copyright 2002, Documentum, Inc") Return True if the String passed as an argument matches a supported version. Otherwise return False. Return True if the String passed as an argument matches a supported feature. Otherwise return False.

getVendorString

isCompatible

supportsFeature

Implement new or overridden methods that embody the TBOs business rules Remember that a future TBO might extend (subclass) the class you write. Be sure to document any problems that programmers might encounter in extending your class. If you must prevent subclassing, consider defining the class to be final.

To override a method of the superclass, it is usually simplest to include a call to the method you are overriding as part of your code. For example,
public void save() { validate(); super.save(); }

// new extra functionality // inherited functionality

Be sure to understand how DFC and other applications use the methods you are overriding. For example, DfSysObject.checkout, calls DfSysObject.checkoutEx(null, null, null). To prevent the kinds of problems that might arise if you override both, DFC declares checkin, checkout, getContent, and several other methods to be final, so that you cannot override them. Use the following guidelines to make your code as close to stateless as possible: An instance of a TBO holds a reference to a specific DFC session object, which it uses during its entire life. Keep the session manager locked to ensure that DFC does not return the session to the pool for reuse. Initiate Client Control using the beginClientControl method before obtaining or creating a TBO instance. Release Client Control using the endClientControl method when finished.
public void doSomething( IDfId idDoc ) { IDfSession session = getSession(); IDfSessionManager sMgr = getSessionManager(); try { sMgr.beginClientControl(); IDfPersistentObject obj = session.getObject( idDoc ); IAutoNumberType autoNumber = (IAutoNumberType)obj; passingObjectToAnotherMethod( obj ); }

86

Developing DFC Applications

Understanding Business Objects

finally { sMgr.endClientControl(); } }

Use the session manager for Docbase sessions whenever possible. Use the IDfTypedObject.setSessionManager method when serializing a TBO or when returning a TBO from a method of an SBO. The following example shows how to return a TBO from within an SBO method. Client Control and setSessionManager are alternative approaches to doing basically the same thing.
public IDfDocument borrow( String strDocbase, IDfId idDoc ) { IDfSession session = null; IDfDocument doc = null; try { session = getSession( strDocbase ); doc = (IDfDocument)session.getObject( idDoc ); doc.setSessionManager( getSessionManager() ); } finally { releaseSession( session ); } return doc; }

When a program calls setSessionManager, DFC performs the following actions: Copy all attributes of the object into a DFC cache on the Java side Sever the persistent object from its original DFC session Store a reference to the specified session manager object in the persistent object

The setSessionManager method allows a program to get and set attributes without communicating with the Docbase. When the program executes a method that requires such communication (for example, save, checkin, checkout), DFC automatically performs the following sequence of actions: Request a session from the session manager Fetch the persistent object Update the attributes from the DFC cache Execute the requested action Release the session

All of this behind-the-scenes activity is invisible to the client application.

Developing DFC Applications

87

Understanding Business Objects

Calling Rules, Guidelines, and Examples


Client applications and methods of SBOs can use TBOs. Use a factory method of IDfSession to instantiate a TBO object. Release the session when you finish with the object. Within a method of an SBO, use getSession to obtain a session. Do not store the TBO in the service, because DFC releases the session when the service method is finished, making the session object invalid. Use the setSessionManager method when you wish to: Release the DFC session but keep an instance of the TBO. Store the TBO in the SBO state.

When calling an SBO method that returns a TBO object, use the client control mechanism (see Client Control, page 125) before and after the call.

Error Handling
The factory methods getObjectWithInterface and getObjectByQualificationWithInterface may throw the execptions shown in the following table.
Table 62. TBO Factory Method Exceptions Exception DfDborNotFoundException Cause DFC cannot find the dbor.properties file. (Check the DFC_DATA environment variable.) DFC cannot find the service in the dbor.properties file. DFC cannot instantiate the class that the dbor.properties file refers to. (If the class is valid, check the CLASSPATH and the permissions on the class.)

DfServiceNotFoundException

DfServiceInstantiationException

Best Practices
This section lists best practices for developing TBOs.

88

Developing DFC Applications

Understanding Business Objects

Do Not Extend DFC Interfaces


For example, if your TBO class extends the DfDocument class, do not define your interface to extend IDfDocument. Extending standard Documentum interfaces leads to unnecessarily complicated TBO interfaces. Because the class extends DfDocument, DFC operations can still use all DfDocument methods. Restrict the public interface to those methods you expect users of the TBO to call directly. The implementation can simply call super.method inside the methods of the class.

Design TBOs That Others Can Extend


Others may wish to extend your TBO to add additional features. For example, the AutoNumberType in chapter 3 generates unique numbers in sequence. Other developers might wish to extend the design with other kinds of unique numbering systems (for example, UUID, stepped numbers), so that AutoNumberType becomes the base of a hierarchy.

Never Replace Documentum Types


Documentum does not support remapping of standard Docbase types to custom classes.

Documentum Business Object Registry (DBOR)


This section describes DBOR. It contains the following main subsections: Overview of DBOR , page 89 Architecture of DBOR, page 90 Using DBOR at Runtime, page 91 Managing DBOR, page 91 Handling DBOR Errors, page 93

Overview of DBOR
The Documentum business object registry (DBOR) is a broker for business objects. Developers register business objects with DBOR, and DFC looks for registered objects at runtime. DBOR maps the Java interfaces of SBOs and the Docbase object types of TBOs to the Java classes that implement the associated business logic. DBOR lets you change implementations without changing the client applications that use the business logic. At runtime, the factory methods for TBOs and SBOs use DBOR to identify the classes to instantiate.

Developing DFC Applications

89

Understanding Business Objects

The IDfDbor interface provides methods for for adding business objects to the registry and for removing them. It provides methods for looking up TBOs by name and SBOs by interface name.

Architecture of DBOR
The files that DFC uses to implement DBOR are in a subdirectory of the directory specified by the environment variable DFC_DATA (usually C:\Documentum). Caution The information in this manual about the current implementation is subject to change without notice. It is to help you in troubleshooting your business applications. Always use the Java interfaces to work with DBOR from your application. The current implementation of DBOR uses the dbor.properties file in the DFC_DATA\config directory. You can override this location by defining a Java system property dfc.data, as follows:
java.exe -Ddfc.data="c:\Documentum" YourProgram

Troubleshooting the Properties File


Use the IDfDbor interface to access registry information. You can add, modify, or enumerate DBOR entries programmatically, using the IDfDbor interface. Doing so prevents duplicate entries. The current implementation (subject to change as noted earlier) uses the dbor.properties file, a plain text file that follows the standard Java properties file syntax. Each line is a DBOR entry. Comment lines start with #.

Deploying DBOR
You must deploy DBOR to every computer that runs DFC-based applications that might use a TBOs or SBO. For example, if you use a TBO or SBO to customize Desktop Client, you must deploy DBOR to each computer running Desktop Client. For WDK, ASP, and JSP environments, you need only deploy DBOR on the application server computers. In the current implementation, deploy DBOR by copying the dbor.properties file into the config subdirectory of the directory defined by the environment variable DFC_DATA. Developing business objects includes the following actions: Incorporate logic to ensure that future updates to your business objects do not introduce version conflicts. Construct a COM interface if a business object adds new methods to a TBO.

90

Developing DFC Applications

Understanding Business Objects

The IDispatch interface makes the classes and methods of business objects available to COM. You can also create an IDL file or a TypeLib file (.TLB). For TBOs, add the new Docbase types to the Docbase. Deploy the business objects: Copy the JAR or WAR file (archive) containing the business objects to the file system. Modify the CLASSPATH to include the archive. Update DBOR to map the associated interfaces or Docbase types to the business object Java classes.

Using DBOR at Runtime


Use the IDfClient.newService factory method to instantiate an SBO. Use the IDfSession.newObject factory method or one of the IDfSession. getObjectXxx methods to instantiate a TBO. These methods look for the SBO or TBO in DBOR. They throw an exception if they dont find the SBO. If there is no DBOR entry for the specified TBO the factory method instantiates an appropriate supertype. For example, if you ask DFC to instantiate a TBO of type dm_autonumber, and if the DBOR lookup fails, DFC instantiates DfSysObject. Updates to DBOR take effect immediately. You need not restart the application to use the updated DBOR entries.

Managing DBOR
Use the methods of the IDfDbor interface to add or remove DBOR items. You can obtain a reference to an IDfDbor object by calling the IDfClient.getDbor method. The table lists the methods of IDfDbor.
Table 63. Methods of IDfDbor Dbor Method register Description Add an IDfDborEntry for an SBO or TBO to DBOR. Throw an exception if the entry name duplicates that of an existing entry. Remove from DBOR the IDfDborEntry whose name you specify. Return the fully qualified name of the Java class that implements the specified SBO. Return the fully qualified name of the Java class that implements the specified TBO. Return an IDfEnumeration of all DBOR entries.

unregister

lookupService

lookupObject

getAll

The following Java code shows how to create and configure an IDfDborEntry:

Developing DFC Applications

91

Understanding Business Objects

boolean mapBusinessObjectToClassName( String strDborName, boolean bDborService, String strJavaClass, String strVersion ) throws DfServiceException, DfDborNotFoundException { boolean bRetVal = false; boolean bAlreadyExists = false; IDfDbor dbor = m_client.getDbor(); String strLookup = null; try { strLookup = dbor.lookupService( strDborName ); bAlreadyExists = true; } // This catch list eats all the exceptions because it expects // that any of the following conditions should still allow us // to continue. catch( DfDborNotFoundException e ) { // dbor.properties file not found } catch( DfServiceCriticalException e ) { // service found, but its a "type" } catch( DfServiceNotFoundException e ) { // service not found } // You should get here...the service should not exist if youre adding. if( !bAlreadyExists ) { try { strLookup = dbor.lookupObject( strDborName ); bAlreadyExists = true; } // This catch list eats all the exceptions because it expects // that any of the following conditions should still allow us // to continue catch( DfDborNotFoundException e ) { // dbor.properties file not found } catch( DfServiceCriticalException e ) { // "type" found, but its a "service" } catch( DfServiceNotFoundException e ) { // type not found } } if( bAlreadyExists ) { System.out.println( strDborName + " already mapped to " + strLookup ); } else { // You should expect to get here... try { String s; // if not already registered... IDfDborEntry entry = new DfDborEntry(); entry.setName( strDborName );

92

Developing DFC Applications

Understanding Business Objects

entry.setServiceBased( bDborService ); entry.setJavaClass( strJavaClass ); entry.setVersion( strVersion ); dbor.register( entry ); System.out.println( "Successful:" ); dbor = null; // unlock DBOR so lookup() can use it. beginList( strDborName ); // displays the entry bRetVal = true; } catch( DfServiceCriticalException e2 ) { // You get here if MSG_DBOR_NOT_DEFINED or MSG_SERVICE_EXISTS System.out.println( "Unable to map dbor entry" ); System.out.println( e2.toString() ); e2.printStackTrace(); bRetVal = false; } catch( DfServiceException e2 ) { // You get here if there is an (DM_VEL_DBOR_IO_ERROR) error // on the registry. System.out.println( "Unable to map dbor entry" ); System.out.println( e2.toString() ); e2.printStackTrace(); bRetVal = false; } } return bRetVal; }//end mapBusinessObjectToClassName()

Handling DBOR Errors


DFC throws exceptions for the following problems that can arise in DBOR registration or lookup: DBOR is not present in expected location Check the DFC_DATA environment variable or the dfc.data system property. DBOR does not contain an entry for the requested SBO DFC throws DfDborNotFoundException. The newService method declares that it throws DfServiceException, which is a supertype of the real exception, DfServiceInstantiationException. If the exception message refers to a class not found condition, the item might not be registered correctly or the classpath may be incorrect. Problems with DBOR registration DFC throws DfServiceCriticalException, which is an unchecked Java runtime exception. This can include DBOR not found, cannot write to file, or service already configured exceptions. Problems with the unregister method

Developing DFC Applications

93

Understanding Business Objects

DFC throws either a DfServiceCriticalException or a DfServiceException. The DfServiceException indicates a problem performing IO on the registry. The DfServiceCriticalException indicates bad arguments to the method, such as an empty name. The DfServiceCriticalException is a runtime exception and does not appear in the throws clause of the method signature.

94

Developing DFC Applications

Chapter 7 Developing Business Objects

This chapter provides step-by-step instructions for developing and deploying a type based object (TBO) and a service based object (SBO). Together, these business objects provide a simple autonumbering capability. The Simple_TBO and Simple_SBO test applications comprise a simplified solution to a real-world business problem, that of maintaining a business-wide sequential numbering system for a variety of purposes, (for example, purchase orders and invoices). This implementation maintains the numeric value used to calculate the next number in a central location and serializes access to the number so that it safely increments sequentially. Client programs that are compatible with this version of DFC immediately begin to use the implementation classes and overridden methods that you develop and deploy. This section contains the following main subsections: Getting Started with BOF, page 95 Overview of the Sample Business Objects, page 96

Getting Started with BOF


Perform the following steps to set up the environment for the example: 1. Install DFC on the client computer. Run the DFC installer, following the instructions in the DFC release notes. The release notes describe the required Java support. 2. 3. Identify a Docbase in which you can run with the necessary permissions. Configure DMCL.INI: Point to a DocBroker to which the Docbase projects. Enable session pooling. Add the following entry to the [DMAPI_CONFIGURATION] section: connect_pooling_enabled = T

Developing DFC Applications

95

Developing Business Objects

4.

Ensure that the CLASSPATH environment variable of your IDE or JVM contains dfc.jar and that the PATH variable contains the directory that contains dmcl40.dll. By default, DFC installs these files in c:\Program Files\Documentum\shared on Windows systems. If you run from within an IDE, for example, IntelliJ or Fort, you must usually make additional CLASSPATH settings.

5.

The DFC_DATA system variable must refer to the directory containing Documentum configuration information (for example, c:\Documentum).

Note: After you develop your business objects, you must make them accessible. You can place them in a jar file and add it to CLASSPATH.

Overview of the Sample Business Objects


This section describes the sample TBO and SBO and shows how they work together to provide autonumbering.

The Simple_TBO Example


The Simple_TBO example provides persistent storage using the current_number attribute of the custom Docbase type com_accelera_autonumber, a subtype of dm_sysobject. Note: Accelera.com is a fictitious domain name that Documentum uses in examples. After studying this sample, you might wish to extend it in any of the following ways: Impose a restriction on the maximum value of a number for a given numbering type, or require that the number be zero-filled to a certain number of digits. Require that purchase order numbers begin with PO, while invoice numbers begin with INV. In this simple example, the user of the IAutoNumber interface can handle this. Alternatively, you might subclass the autonumber type. Use separate numbering sequences for purchase orders and invoices, because it is usually not desirable to mix them, as in PO001, INV002, PO003, INV004.

To implement these extensions, you must override such methods of dm_sysobject as checkin, checkout, and save for the custom type.

The Simple_SBO Example


The Simple_SBO example provides an interface for obtaining the correct centralized number and saving it to the TBO. It provides methods for fetching the stored value and saving the next number in the Docbase. These methods hide the details of locking and unlocking the TBO objects, fetching and saving other attributes of the TBO objects, and so on.

96

Developing DFC Applications

Developing Business Objects

The most important method of this service is the getUniqueNumber method, which fetches and increments the number according to the number type (PO, INV, etc.). The other methods of this service are mainly for management purposes. Another method is setNumber, used internally to set the initial number value for a given number type and to save the calculated value back to the Docbase. A fully functional service of this type provides number formatting patterns and other filters.
Figure 71. AutoNumber Schema

MUST CHANGE LABEL TO SAY AUTONUMBER, NOT AUTONAME

A Simple TBO Example


Introduction
The Simple_TBO program fetches the Docbase object containing the existing number, increments it, and saves the newly incremented value back to the Docbase. To accomplish this, the program provides the following features and capabilities: A Docbase type called com_accelera_autonumber, which is a subtype of the dm_sysobject Docbase type. Each Docbase object of the type has an attribute called current_number to store the last value returned from the getUniqueNumber method. The new type defines the schema for the different numbering schemes, called numbering types in this example.

Developing DFC Applications

97

Developing Business Objects

A Java class called AutoNumberType to provide methods for incrementing the number. The AutoNumberType class inherits from (extends) DfSysObject and overrides DfSysObject methods like checkin and save to guarantee that the number is always within the bounds set for its type. The class implements all of the DfSysObject methods that it overrides and also implements its own methods (getUniqueNumber, checkRange, and so forth). The classs methods use the current_number value of the Docbase object to calculate the next number in the sequence defined for the given numbering type. The class also defines members to store any other necessary persistent information (see Table 71, page 98). The AutoNumberType class has a static method, addNewAutoNumberType, that can create com_accelera_autonumber Docbase objects. This method uses the newObject factory method of IDfSession factory method to create a new instance of the com_accelera_autonumber type.

An interface, IAutoNumberType, that AutoNumberType implements. This interface exposes the public behavior of the AutoNumberType class. The interface could extend IDfSysObject, but Documentum recommends against this (see Implementation Rules, Guidelines, and Examples, page 85).

Table 71. Sample com_accelera_autonumber Objects and Their Values r_object_id name type_name current_ number 590124 30822 944 max_number

090000000101a8b7 Purchase Order 090000000101a8cb Invoice 090000000101af58 Patent Application 090000000101b032 Contract Document

PO INV DCMPAT

99999999999 99999999999 9999999

DCMCON

730822

99999999

The Simple_TBO class is a standalone Java application that tests AutoNumberType by obtaining and outputting the current number, causing the number to increment and storing it back into the Docbase. Simple_TBO calls the static addNewAutoNumberType method to create a new instance of the com_accelera_autonumber type if it cant find the specified type. A Simple_TBO test application is stateless from the TBO perspective, in that it executes and ends with each invocation. Running Simple_TBO from different computers will retrieve numbers in sequence relative to the com_accelera_autonumber Docbase object, independently of the computer or the Simple_TBO instance. In order to develop the TBO described here, carry out the following steps: 1. 2. 3. Create the IAutoNumberType Java interface. Create the AutoNumberType Java class. Create the com_accelera_autonumber Docbase type

98

Developing DFC Applications

Developing Business Objects

4. 5.

Register the AutoNumberType class with DBOR. Create the Simple_TBO Java program to test the TBO.

A Simple SBO Example, page 112 shows how to develop a service-based business object (SBO) to access this TBO.

Creating the IAutoNumberType Interface


This section shows how to create an interface for the new TBO. To define the interface: 1. Define a new interface called IAutoNumberType that extends the IDfBusinessObject interface.

The IDfBusinessObject interface defines four abstract methods. Classes that implement the interface must provide concrete versions of these. 2. In IAutoNumberType, prototype the getUniqueNumber method.

In general, prototype the methods that you wish to expose publicly.


/* IAutoNumberType.java */ package com.accelera.autonumber; import com.documentum.fc.client.*; import com.documentum.fc.common.DfException; public interface IAutoNumberType extends IDfBusinessObject { public String getUniqueNumber( IDfSessionManager sMgr ) throws DfException; }

Creating the AutoNumberType Class


This section shows how to create the class that implements the TBO. To create the class that implements the TBO: 1. Create AutoNumberType to extend DfSysObject.

The AutoNumberType TBO class definition wraps a Docbase object of type com_accelera_autonumber and provides methods to get and set the objects attributes. It implements methods to override the checkin and save methods of .DfSysObject The AutoNumberType class inherits all methods and properties of DfSysObject and IAutoNumberType. Through IAutoNumberType it also inherits the methods and properties of IDfBusinessObject. You need not rewrite or override inherited methods whose behavior you do not wish to alter. For example, the IAutoNumberType interface allows users of the object to call the checkin method on the interface, but does not provide new behavior.

Developing DFC Applications

99

Developing Business Objects

Thus it declares the checkin method in the interface, but lets the class inherit the method from DfSysObject. The AutoNumberType class extends DfSysObject by changing the behavior of two of its methods, save and checkinEx, and by adding six new methods related to autonumbering. The new methods are getUniqueNumber, setNextNumber, setNumber, checkRange, validate, and addNewAutoNumberType.
/* AutoNumberType.java */ package com.accelera.autonumber; import com.documentum.fc.client.*; import com.documentum.fc.common.*; public class AutoNumberType extends DfSysObject implements IAutoNumberType { }

2.

Implement the methods of IDfBusinessObject a. In the AutoNumberType class, add the String constants to use with the getVersion and getVendorString methods.
public static final String strCOPYRIGHT = "Copyright (c) Documentum, Inc., 2003"; public static final String strVERSION = "1.0";

b.

Implement overrides for each of the four abstract methods of IDfBusinessObject, namely, getVersion, getVendorString, isCompatible, and supportsFeature, as follows:

/* AutoNumberType.java */ package com.accelera.autonumber; import com.documentum.fc.client.*; import com.documentum.fc.common.*;

public class AutoNumberType extends DfSysObject implements IAutoNumberType { public static final String strCOPYRIGHT = "Copyright (c) Documentum, Inc., 2002"; public static final String strVERSION = "1.0";

public String getVersion() { return strVERSION; } public String getVendorString() { return strCOPYRIGHT; } public boolean isCompatible( String s ) { return s.equals("1.0");

100

Developing DFC Applications

Developing Business Objects

} public boolean supportsFeature( String s ) { String strFeatures = "uniquenumber, subclassing"; if( strFeatures.indexOf( s )== -1 ) return false; return true; } }

3.

Inside the AutoNumberType class, override the save and checkinEx methods of DfSysObject to call the validate method before forwarding the call to its superclass implementation.

The service, and any other user of the Docbase object modifies it using combinations of the checkout method with save or checkin. The checkin method calls checkinEx, so checkinEx is a better method to override than checkin. In any event, the checkin method is final, so you cannot override it.
public void save() throws DfException { validate(); super.save(); } public IDfId checkinEx( boolean fRetainLock, String strVersionLabels, String strOldCompoundArchValue, String strOldSpecialAppValue, String strNewCompoundArchValue, String strNewSpecialAppValue ) throws DfException { validate(); return super.checkinEx( fRetainLock, strVersionLabels, strOldCompoundArchValue, strOldSpecialAppValue, strNewCompoundArchValue, strNewSpecialAppValue ); }

Note: Certain DFC methods call other methods to perform their basic tasks. When overriding methods, try to avoid performing the same override twice by overriding the lowest level routine that performs the task you wish to alter. DFC declares some methods to be final to help you avoid overriding the wrong method. The checkin, checkout, and getContent methods of IDfSysObject are examples. When in doubt about which method to override, you might wish to perform a trace to see which methods call which in all of the environments from which you expect people to access your business object. For example, the Documentum products WDK and Desktop Client use DFC in different ways. 4. Implement the new methods of the AutoNumberType class: a. Implement the getUniqueNumber, setNextNumber, and setNumber methods.

Developing DFC Applications

101

Developing Business Objects

The getUniqueNumber method fetches the value of its current_number attribute. The setNextNumber method increments its current_number attribute, validates that its value is within the business rules, and saves the new number into its current_number attribute. The setNumber method establishes the initial value of the current_number field. By default, Simple_TBO sets current_number to 1. Lines 22, 23, and 24 of the following example must comprise an atomic operation to ensure that the method never supplies duplicate numbers. Because Documentum does not support nested session transactions, this code requires the caller to open a managed transaction. The code on lines 13 through 18 tests for this and throws an exception if the caller has not called from within a managed transaction. Implement the methods as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public String getUniqueNumber( IDfSessionManager sMgr ) throws DfException { return setNextNumber( sMgr ); }

private String setNextNumber( IDfSessionManager sMgr ) throws DfException { String strRetVal = null; if( ! sMgr.isTransactionActive() ) { DfException e = new DfException(); e.setMessage( "no transaction available" ); throw e; } try { checkout(); // lock strRetVal = setNumber( null ); save(); // unlock and update } catch( DfException e ) { sMgr.setTransactionRollbackOnly(); e.setMessage( strRetVal + e.getMessage()); throw e; } return strRetVal; }//end setNextNumber()

public String setNumber( String strNewNumber ) throws DfException { if( strNewNumber != null ) { setString( "current_number", strNewNumber );

102

Developing DFC Applications

Developing Business Objects

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

} else { strNewNumber = getString( "current_number" ); long n = Long.parseLong( strNewNumber ); checkRange( n+1 ); strNewNumber = String.valueOf( ++n ); setString( "current_number", strNewNumber ); } return strNewNumber; }

b.

Implement the validate and checkRange. methods.

The checkRange method checks a numeric value for validity before attempting to save it into the Docbase object. The validate method fetches the "current_number" from the object and forwards it to the checkRange method for validation. These methods throw an exception if the number does not follow the business rules.
protected void validate() throws DfException { String s = getString( "current_number" ); checkRange( Long.parseLong(s) ); }//end validate() protected void checkRange( long n ) throws DfServiceException { String strMsg = "checkRange() Docbase error"; try { long lMax = this.getLong( "max_number"); if( ( n < 0 ) || ( n > lMax ) ) { strMsg = "bad number or number out of range: " + String.valueOf( n ) + ", " + String.valueOf( lMax ); DfServiceException ex = new DfServiceException( this, strMsg ); DfLogger.error( this, strMsg, null, ex ); throw ex; } } catch( DfException e ) { DfLogger.error( this, strMsg, null, e ); throw new DfServiceException( e, strMsg ); } }//end checkRange()

c.

Implement the addNewAutoNumberType method.

This is a static member of the AutoNumberType class. Call it to create instances of the class. Each instance of the AutoNumberType is tied to a version of a Docbase object with its own r_object_id. Call the addNewAutoNumberType method whenever

Developing DFC Applications

103

Developing Business Objects

you need to start a new numbering sequence. It sets the starting number and the maximum range to the specified values.
public static void addNewAutoNumberType( IDfSessionManager sMgr, String strDocbase String strTableName, String strObjectName, // long name String strAutoNumberType, String strStartingNumber, String strMaxNumber, String strDocbaseFolder ) throws DfException { IDfSession session; try { session = sMgr.getSession( strDocbase ); AutoNumberType number = (AutoNumberType) session.newObject( strTableName ); number.setObjectName( strAutoNumberType ); number.setString( "number_type", strAutoNumberType ); number.setString( "max_number", strMaxNumber ); number.setNumber( strStartingNumber ); number.save(); DfLogger.error(number, "new %s instance added:%s", new String[]{ strTableName, strAutoNumberType }, null); } catch( Exception e ) { // failed to create if( e instanceof DfException ) throw (DfException)e; throw new DfException( DfException.DM_NOTDFC_E_JAVA, e.toString() ); } }//end addNewAutoNumberType()

5.

Create the new dm_type instance as "com_accelera_autonumber"

The new custom type is a subtype of dm_sysobject. Each different auto-numbering type will have its own instance of this new type. There are several ways to create the new com_accelera_autonumber custom type. Use Documentum Developer Studio to develop a portable DocApp:

104

Developing DFC Applications

Developing Business Objects

Figure 72. Installing a new Docbase Type

Use the IDQL tool to use DQL to manually create the new com_accelera_autonumber type to a Docbase.
create type com_accelera_autonumber (number_type char(128), current_number char(18), max_number char(18)) with supertype dm_sysobject

Write a program that adds the new com_accelera_autonumber type to a Docbase.


IDfQuery query = new DfQuery(); query.setDQL( "create type com_accelera_autonumber" + " (number_type char(128), current_number char(18), " + " max_number char(18)) with supertype dm_sysobject" ); IDfCollection coll = query.execute( session, IDfQuery.DF_EXEC_QUERY ); coll.close();

6.

Ensure that the new class appears in the CLASSPATH.

Creating the com_accelera_autonumber Docbase Type


This section shows how to create the Docbase type to support the TBO. The com_accelera_autonumber Docbase type is a subtype of dm_sysobject. Each auto-numbering type has its own instance of this type. You can use any of the following ways to create the com_accelera_autonumber Docbase type: Use Documentum Developer Studio.

Developing DFC Applications

105

Developing Business Objects

Figure 73. Installing a new Docbase Type

Use the IDQL tool to create and execute the following DQL statement:
create type com_accelera_autonumber ( number_type char(128), current_number char(18), max_number char(18) ) with supertype dm_sysobject

Execute a Java program similar to the following:


IDfQuery query = new DfQuery(); query.setDQL( "create type com_accelera_autonumber" + " (number_type char(128), current_number char(18), " + " max_number char(18)) with supertype dm_sysobject" ); IDfCollection coll = query.execute( session, IDfQuery.DF_EXEC_QUERY ); coll.close();

Registering the TBO with DBOR


This section shows how to register the TBO with DBOR. Map the new com_accelera_autonumber Docbase type to the new business object class In the "DFC_DATA\config" directory (usually "c:\Documentum\config"), add the following entry anywhere in the dbor.properties file:
com_accelera_autonumber=type,com.accelera.autonumber.AutoNumberType,1.0

106

Developing DFC Applications

Developing Business Objects

This registers the new business object with Documentum 5.1 so that any time any Docbase objects from this new table are fetched, the Docbase object is used to populate the AutoNumberType object. Caution The current implementation of DBOR uses the dbor.properties file in the DFC_DATA\config directory. Documentum will change this in future releases. Both the implementation of the object registry and the use of the config directory will change. The information regarding the use of the dbor.properties file is included in this manual in case you need to debug your business applications. Always use the DBOR maintenance tool to edit this file. You should write a program that uses the IDfDbor and IDfDborEntry interfaces to register the AutoNumberType business object.
boolean mapDocbaseTypeToClassName( IDfSession session, boolean bDborService, String strDocbaseTypeName, String strJavaClass ) { boolean bRetVal = true; IDfClient client = session.getClient(); IDfDbor dbor = client.getDbor(); String strLookup = null; try { System.out.println( "mapping " + strDocbaseTypeName ); if( ! bDborService ) { strLookup = dbor.lookupObject( strDocbaseTypeName ); } else { strLookup = dbor.lookupService( strDocbaseTypeName ); } System.out.println( strDocbaseTypeName + " already mapped to " + strLookup ); bRetVal = true; } catch( Exception e ) { try { String s = e.toString(); // if not already registered... IDfDborEntry entry = new DfDborEntry(); entry.setName( strDocbaseTypeName ); entry.setServiceBased( bDborService ); entry.setJavaClass( strJavaClass ); entry.setJavaClass( AutoNumberType.class.getName() ); entry.setVersion( "1.0" ); dbor.register( entry ); System.out.println( "New dbor registry entry successfull" ); } catch( Exception e2 ) { System.out.println( "Unable to map dbor entry" ); System.out.println( e2.toString() ); e2.printStackTrace(); bRetVal = false;

Developing DFC Applications

107

Developing Business Objects

} }//end catch( DfDborNotFoundException )

return bRetVal; }

In the mapDocbaseTypeToClassName method above, the dbor.register method signals that there is already an entry by throwing an exception. In other words, duplicate entries are not possible when the IDfDbor interface and should be the only mechanism used to manipulate the registry. An entry is duplicated when the name is the same. For TBOs, a duplicate entry when two or more entries have the same values left of the equals for the Docbase type. For services, it is the service interface name that must be unique. Editing DBOR by hand is strongly discouraged. Doing so could create serious runtime problems with the other Documentum based applications on your system. If the dbor.properties file does not exist, the register method will cause one to be created.

Testing the TBO


This test program is designed to mimic a regular caller/consumer of a TBO object. 1. 2. Create the new Simple_TBO class Declare the private instance variables
/* Simple_TBO.java */ import java.util.Collection; import com.documentum.fc.client.*; import com.documentum.fc.common.*; import com.documentum.com.*; import com.accelera.autonumber.*;

public class Simple_TBO { private private private private String String String String m_strDocbaseName; m_strUserName; m_strPassword; m_strDomain;

private static final String m_strAutoNumberTable = "com_accelera_autonumber"; private String m_strAutoNumberType; }

3.

Write the main and begin methods and instantiate the Simple_TBO class. This involves parsing the command line arguments into variables, instantiating the

108

Developing DFC Applications

Developing Business Objects

Simple_TBO class to prevent writing all the methods and variables as static, establishing a session manager identity, and calling the test routine. 4. In the begin method, construct a new session manager object using the newSessionManager method of IDfClient. Then register a users credentials as an identity in the session manager, using the IDfSessionManager.setIdentity method.
public static void main( String[] args ) { new Simple_TBO().begin( args ); //xfer control to a non-static method } void begin( String[] args ) { try { // check cmd args if( !parseCmdLine( args ) ) return; IDfClient client=null; client = DfClient.getLocalClient(); IDfClientX clientx = new DfClientX(); IDfLoginInfo login = clientx.getLoginInfo(); login.setUser( m_strUserName ); login.setPassword( m_strPassword ); if( m_strDomain != null ) login.setDomain( m_strDomain ); // connect to session mgr IDfSessionManager sMgr = client.newSessionManager(); sMgr.setIdentity( m_strDocbaseName, login); test( sMgr, m_strDocbaseName, m_strAutoNumberTable, m_strAutoNumberType ); } catch( Exception e ) { DfLogger.error(this, e.toString(), null, e); } }

5.

Parse the command line arguments into private variables


private boolean parseCmdLine( String[] args ) { try { m_strDocbaseName = args[0]; // check DocbaseName m_strAutoNumberType = args[1]; m_strUserName = args[2]; // check AutoNumberType m_strPassword = args[3]; // check Java class name if( args.length > 4 ) { m_strDomain = args[4]; } }

Developing DFC Applications

109

Developing Business Objects

catch( Exception e ) // array bounds exceptions, etc. { System.out.println( "Error parsing command line arguments.\n" ); System.out.println( "Usage: java Simple_TBO " + "<docbase> <newAutoNumberType> " + "<user> <password> [<domain>]\n\n" ); System.out.println( "Be sure that the following DMCL.INI file " + "has the following settings:" ); System.out.println( " [DMAPI_CONFIGURATION]" ); System.out.println( " connect_pool_enabled=T\n\n" ); } return true; }

6. 7.

Test the new object type. To test the new business object, fetch a specified instance of a "com_accelera_ autonumber" type (like PO, or INV). If no matching "number_type" exists, then a new one is added for you with its starting number set to "1". Then call the getUniqueNumber method. Display the number you retrieved.

8. 9.

10. Set the next number back into the Docbase and release any locks you may have established on the object. 11. Save the object with the overridden save method.
void test( IDfSessionManager sMgr, String strDocbaseName, String strAutoNumberTable, String strAutoNumberType ) throws DfException { sMgr.beginTransaction(); try { IAutoNumberType number = null; IDfSession session = sMgr.getSession( strDocbaseName ); try { String strDQL = strAutoNumberTable + " where number_type=" + strAutoNumberType + ""; // GOOD EXPERIMENT! // Find the r_object_id of the AutoNumberType record and use it in // the query below as follows: // String strDQL = "dm_sysobject where r_object_id = 09...."; number = (IAutoNumberType) session.getObjectByQualification( strDQL ); // If it doesnt exist, tell the class to add one for you. if( number == null ) { AutoNumberType.addNewAutoNumberType( sMgr, strDocbaseName, strAutoNumberTable, strAutoNumberType, strAutoNumberType,

110

Developing DFC Applications

Developing Business Objects

"1", "999999999999", "/System/com_accelera_autonumber" ); number = (IAutoNumberType) session.getObjectByQualification( strDQL ); } String strNewNumber = number.getUniqueNumber( sMgr ); System.out.println( "Current number for " + strAutoNumberType + " is: " + strNewNumber ); } finally { sMgr.release( session ); } sMgr.commitTransaction(); } catch( Exception e ) { DfLogger.error(this, "failed to update", null, e); DfLogger.error(this, e.toString(), null, e); sMgr.abortTransaction(); // failed to create or update if( e instanceof DfException ) throw (DfException)e; DfException e2 = new DfException(); e2.setMessage( e.toString() ); throw e2; } }

Executing this command line several times for different numbering types will prove that the service is producing sequential numbers by type:
Figure 74. Run the test TBO program

Developing DFC Applications

111

Developing Business Objects

A Simple SBO Example


Introduction
The SBO in this example fetches the next sequence number according to the specified number type in the given Docbase and increments it. It supports multiple numbering sequences (for example, PO, INV). It use the AutoNumberType TBO developed in A Simple TBO Example, page 97. In order to develop the SBO described here, carry out the following steps: 1. 2. 3. 4. 5. Define the IAutoNumber Java interface. Define the AutoNumber Java class. Deploy the service. Register the service with DBOR. Create and run the Simple_SBO Java test program.

Defining the IAutoNumber Interface


This section shows how to define the IAutoNumber interface, which forms the basis of the example. To create a service interface you must define an interface that does the following: Define the new interface to extend the IDfService interface. This means that any class that implements the new interface must implement the abstract methods of the IDfService interface. Prototype the methods that abstract the details of the service. In this case the interface prototypes the getNextNumber method. The following code defines the interface:
/* IAutoNumber.java */ package com.accelera.autonumber; import com.documentum.fc.client.*; import com.documentum.fc.common.DfException; public interface IAutoNumber extends IDfService { public String getNextNumber( String strDocbase, String strAutoNumberType ) throws DfException; }

112

Developing DFC Applications

Developing Business Objects

Defining the AutoNumber Class


This section shows how to define a Java class that implements the IAutoNumber interface. To provide a service that implements the IAutoNumber interface, the class must do the following: Extend the DfService class. Implement the abstract methods of the DfService class. Implement the getNextNumber method of the IAutoNumber interface.

The AutoNumber SBO class definition provides a very simple generalized interface to the TBOs stored in the Docbase. Aside from Docbase session and synchronization issues, the caller need not be aware of the underlying details as to how the service performs its duty. The caller just calls getNextNumber and the service takes care of the rest. Before implementing the getNextNumber method, override the three abstract methods from DfService that you must implement.

Extending the DfService Class


Create a new class, AutoNumber, and extend the DfService class to implement its IAutoNumber interface.
public class AutoNumber extends DfService implements IAutoNumber { }

Implementing Abstract Methods of DfService


The AutoNumber class extends the DfService class, which defines three abstract methods: getVersion, getVendorString , and isCompatible. First, define String constants for use in the getVersion and getVendorString methods:
public static final String strCOPYRIGHT = "Copyright (c) Documentum, Inc., 2003"; public static final String strVERSION = "1.0";

Next, define the three methods, as follows:


/* AutoNumber.java */ package com.accelera.autonumber; import com.documentum.fc.client.*; import com.documentum.fc.common.DfException;

public class AutoNumber extends DfService implements IAutoNumber { public static final String strCOPYRIGHT = "Copyright (c) Documentum, Inc., 2003";

Developing DFC Applications

113

Developing Business Objects

public static final String strVERSION = "1.0"; public String getVersion() { return strVERSION; } public String getVendorString() { return strCOPYRIGHT; } public boolean isCompatible( String strVersion ) { int i = strVersion.compareTo( getVersion() ); if( i <= 0 ) return true; else return false; } } //end: class AutoNumber

Implementing the getNextNumber method of IAutoNumber


Now implement the methods in the service interface that are specific to this service. In the case of the IAutoNumber interface, this is the single method, getNextNumber. To make the getNextNumber method as stateless as possible, we make the Docbase name the first argument. The second argument is the numbering type (for example, PO or INV). The method performs a Docbase query to obtain the matching AutoNumberType object, and to fetch and update its number. The method assumes that the caller has established a session manager, which the method uses to obtain a session with which to access the Docbase. The method uses the getObjectByQualification method of IDfSession to fetch an appropriate AutoNumberType Docbase object, get its next number, and update the number in the object. Because each getSession call must have a matching releaseSession call, the releaseSession call is in a finally block to ensure that it executes.
public String getNextNumber( String strDocbase, String strAutoNumberType ) throws DfException { String strRetVal = null; IDfSession session = null; boolean bNewTransaction = false; String strPrefix = "com_accelera_autonumber where number_type="; String strSuffix = ""; StringBuffer strbDql = new StringBuffer( strPrefix.length() + strAutoNumberType.length() + strSuffix.length() );

114

Developing DFC Applications

Developing Business Objects

String strDql = strbDql.append( strPrefix ) .append( strAutoNumberType ) .append( strSuffix ) .toString(); IDfSessionManager sMgr = getSessionManager(); if( ! isTransactionActive() ) { sMgr.beginTransaction(); bNewTransaction = true; } try { session = getSession( strDocbase ); //managed session try { IAutoNumberType numType = (IAutoNumberType) session.getObjectByQualification( strDql ); strRetVal = numType.getUniqueNumber( sMgr ); } finally { releaseSession( session ); } if( bNewTransaction ) sMgr.commitTransaction(); } catch( Exception e ) { if( bNewTransaction ) sMgr.abortTransaction(); } return strRetVal; }

Deploying and Registering the Service


Once the program compiles successfully, deploy it by placing it in CLASSPATH. Optionally, you can pass a CLASSPATH as a command-line argument as follows:
java -cp ".;%classpath% " Simple_SBO accelera "INV" username password, domain

In order to allow the newService method to know that it should instantiate the AutoNumber class for this service, the DBOR must contain an association between the IAutoNumber interface and the AutoNumber class. You can register this association by using the IDfDbor interface. The beginInstall method registers TBO or SBO entries. If you call it with bService set to true, the strNewDocbaseType parameter represents the service interface (for example, com.accelera.autonumber.IAutoNumber).
private boolean beginInstall( IDfSessionManager sMgr, boolean bService, String strDocbaseName, String strNewDocbaseType,

Developing DFC Applications

115

Developing Business Objects

String strJavaClass ) { boolean bRetVal = true; IDfSession session = null; try { //setupLog(); session = sMgr.getSession( strDocbaseName ); if( ! bService ) { if( addDocbaseType( sMgr, session, strNewDocbaseType ) ) { bRetVal = mapDocbaseTypeToClassName( session, bService, // TBO strNewDocbaseType, strJavaClass ); addDocbaseFolder( session, strNewDocbaseType, "/System" ); } } else { bRetVal = mapDocbaseTypeToClassName( session, bService, // SBO strNewDocbaseType, strJavaClass ); } } catch( Exception e ) { bRetVal = false; } finally { if( session != null ) sMgr.release( session ); } return bRetVal; }

Implementing the Simple_SBO Test program


The test program mimics a caller/consumer of the SBO service. The program defines variables, then the main method. It instantiates the Simple_SBO class (to prevent writing all the methods and variables as static), and passes control to the non-static method. The begin method consists of a single try...catch block. If an error occurs, it prints diagnostic information and exits. The begin method constructs a new session manager object using the newSessionManager method of IDfClient. Then it registers an identity in the session manager, using the setIdentity method of IDfSessionManager. Finally, it calls the test method.
// Simple_SBO.java

116

Developing DFC Applications

Developing Business Objects

import java.util.Collection; import com.documentum.fc.client.*; import com.documentum.fc.common.*; import com.documentum.com.*; import com.accelera.autonumber.*;

public class Simple_SBO { private String m_strDocbaseName; private String m_strUserName; private String m_strPassword; private String m_strDomain; private String m_strAutoNumberType; private static final String m_strAutoNumberTable = "com_accelera_autonumber"; public static void main( String[] args ) { //xfer control to a non-static method new Simple_SBO().begin( args ); } void begin( String[] args ) { try { // check cmd args if( !parseCmdLine( args ) ) return; IDfClient client = DfClient.getLocalClient(); IDfClientX clientx = new DfClientX(); IDfLoginInfo oLogin = clientx.getLoginInfo(); oLogin.setUser( m_strUserName ); oLogin.setPassword( m_strPassword ); if( m_strDomain != null ) oLogin.setDomain( m_strDomain ); // connect to session mgr IDfSessionManager oSMgr = client.newSessionManager(); oSMgr.setIdentity( m_strDocbaseName, oLogin); // fetch, display, then increment the num from service test( oSMgr, m_strDocbaseName, m_strAutoNumberTable, m_strAutoNumberType ); } catch( Exception e ) { System.out.println( e.toString() ); e.printStackTrace(); } } }// end: class Simple_SBO

The code for parsing the command line arguments is as follows:

Developing DFC Applications

117

Developing Business Objects

private boolean parseCmdLine( String[] args ) { try { m_strDocbaseName = args[0]; // check DocbaseName m_strAutoNumberType = args[1]; m_strUserName = args[2]; // check AutoNumberType m_strPassword = args[3]; // check Java class name if( args.length > 4 ) { m_strDomain = args[4]; } } catch( Exception e ) // array bounds exceptions, etc. { System.out.println( "Error parsing command line arguments.\n" ); System.out.println( "Usage: java Simple_SBO " + "<docbase> <newAutoNumberType> " + "<user> <password> [<domain>]\n\n" ); System.out.println( "Be sure that the following DMCL.INI file " + "has the following settings:" ); System.out.println( " [DMAPI_CONFIGURATION]" ); System.out.println( " connect_pool_enabled=T\n\n" ); e.printStackTrace(); } return true; }

The test method gets a session for the given Docbase from the session manager and ensures that it releases the session before exiting. The code for the test method is as follows:
void test( IDfSessionManager sMgr, String strDocbaseName, String strAutoNumberTable, String strAutoNumberType ) throws DfException { try { IDfSession session = sMgr.getSession( strDocbaseName ); IDfClient client = DfClient.getLocalClient(); IAutoNumber svcNumber = null; try { String s = IAutoNumber.class.getName(); svcNumber = (IAutoNumber)client.newService( s, sMgr ); } finally { sMgr.release( session ); } String strNewNumber = svcNumber.getNextNumber( strDocbaseName, strAutoNumberType ); System.out.println( "Current svcNumber for " + strAutoNumberType + " is: " + strNewNumber ); }

118

Developing DFC Applications

Developing Business Objects

catch( Exception e ) { System.out.println( "failed to update" ); // failed to create or update if( e instanceof DfException ) { throw (DfException)e; } DfException e2 = new DfException(); e2.setMessage( e.toString() ); throw e2; }

}//end test()

Running the Simple_SBO Test Program


java -cp ".;%classpath%" Simple_SBO PubsRM "INV" username password domain

Executing this command line several times for different numbering types tests whether the service produces a different sequence of numbers for each type:
Figure 75. Sample running test SBO program

Developing DFC Applications

119

Developing Business Objects

120

Developing DFC Applications

Chapter 8 Using and Deploying Business Objects


Using Business Objects
Overview
This chapter is designed to provide guidelines for using business objects from different environments. In addition, there are several samples provided to demonstrate the issues. The major sections of this chapter are: Managing Sessions for Business Objects How to use a business object from WDK How to use a business object from Visual Basic using IDispatch

Managing Sessions for Business Objects


This section presents Session Manager related considerations for the implementation of service based business objects. Refer to for details on implementing them.

Overview
When implementing a service BO, the session manager is inherently available to the service methods. The session manager object is a member of the DfService class that you extend and can be accessed from any method of a service. In most cases however, the implementation does not directly use the session manager but uses the two convenience methods in DfService (getSession, and releaseSession) which are used to obtain a DFC session handle and return it when finished.

Requesting a DFC Session


For services, the DFC sessions are not typically requested directly from the session manager but through the service parent class, DfService, using the inherited getSession method. The methods of the service then use normal DFC calls to execute the service functionality (business rules). To request a new session, use the sMgr.newSession method. For details on requesting a DFC session, please refer to the section IDfService and DfService objects in.

Developing DFC Applications

121

Using and Deploying Business Objects

Releasing a DFC Session


When a service has finished processing (usually before the service method returns), the DFC session object MUST be returned to the session manager even if a program error occurs. Otherwise, the session pool becomes stalled. Use Javas try/finally termination handler to guarantee the release of the session object. A catch statement is not mandatory. The following example shows a service that requests a session, performs some action, then returns the session back to the session manager.
IDfSession sess = this.getSession( strDocbase ); try { // do something with the Docbase } finally { this.releaseSession( sess ); }

Managing Docbase Names


The methods of the service need a Docbase name before a managed session can be obtained. Several strategies can be used to handle the Docbase name: Pass the Docbase name to every service method. This allows a truly stateless operation and is recommended whenever possible. Store the Docbase name in an instance variable of the service object and provide a setter method (for example, setDocbase(strDocbase)). When the method is called, the Docbase is available from all the service methods. Extract the Docbase name from an object ID. Sometime there are methods that take an object ID as an argument. In this case it is possible to extract the Docbase name from the objects ID (client.getDocbaseNameFromId in IDfClient method).

It is up to the developer to find the right balance of these three approaches.

Transaction Processing
DFC now supports two different transaction-processing mechanisms to assist in management of the granularity of batch updates, session transactions (also called "DFC transactions" using session.beginTrans) and session manager transactions (also called "managed transactions" using sMgr.beginTransaction). DFC session transactions are not allowed inside service methods because they may interfere with transactions controlled by its caller if used. Therefore, a standard DFC session transaction call will throw an exception while inside a BOF transaction. Exercise caution when using transaction processing within a business object service.

122

Developing DFC Applications

Using and Deploying Business Objects

Never begin a transaction if one is already active. Use the sMgr.isTransactionActive() method to determine this. Always use managed transactions within a business object. This is because the isTransactionActive method will not return true if a DFC session transaction is active. It only works with managed transactions. If the service did not begin the transaction, commitTransaction and abortTransaction should not be used within the service method. If abortTransaction() is required, use sMgr.setTransactionRollbackOnly.

When you need the flow of a program to continue when transaction errors occur, use the sMgr.setTransactionRollbackOnly method to ensure transactions will be aborted without throwing an exception; even if the calling program attempts to commit their transaction. Use the setTransactionRollbackOnly method as you would use sMgr.abortTransaction. Any attempt to commit that transaction afterward will be ignored and no error will be generated. In other words, the owner of the transaction would not be aware that one of its method calls aborted the transaction for it unless it calls the getTransactionRollbackOnly method, which returns true if some part of the program ever called setTransactionRollbackOnly. The way it actually works is that when the sMgr.commitTransaction method is eventually called, internally it is redirected to sMgr.abortTransaction. A key point about this is that setTransactionRollbackOnly does NOT throw an exception, so the program continues as if the batch process is valid. When more than one thread is involved in session manager transactions, calling sMgr.beginTransaction from a second thread causes the session manager to automatically create a new session for the new thread.
void serviceMethodThatRollsBack( String strDocbase, IDfId idDoc ) throws DfNoTransactionAvailableException { IDfSessionManager sMgr = getSessionManager(); IDfSession = getSession( strDocbase ); if( ! isTransactionActive() ) { throw DfNoTransactionAvailableException(); } try { IDfPersistentObject obj = session.getObject( idDoc ); obj.checkout() modifyObject( obj ); obj.save(); } catch( Exception e ) { // setTransactionRollback() acts like an abortTransaction() // so that even if they commit after this, this checkout() // and save() are omitted. setTransactionRollbackOnly(); throw new DfException(); } }

Developing DFC Applications

123

Using and Deploying Business Objects

Transaction Handling
The session manager supports transaction handling across multiple services. The session manager handles session pooling details and prevents sessions from being disconnected or released while transactions are pending. When session pooling is used, it is possible that DFC sessions could timeout and be recycled back to the pool between individual service calls. For example, lets say there are two services: one service creates a few folders and then the second service stores some documents in these folders. To make sure the folders are only created when all the document creation has succeeded there must be one transaction around the two service calls. The DFC session transaction is bound to one DFC session so it is important to use the same DFC session across the two services calls. Each service performs its own atomic operation. At the start of each operation, they request a DFC session and at the end they release this session back to the session pool. In between these calls, the service session could have been recycled back to the session pool and released, due to a session timeout. Calling session.beginTrans / session.commitTrans / session.abortTrans could fail. To "lock" a managed session to prevent it from being recycled due to timeouts, the session Manager defines methods that allow transactions to work across multiple service calls and even across Docbases. The Session Manager automatically determines when a session can be put back into the pool. A managed session will not be recycled back into the session pool as long as there is a pending transaction. The sMgr.beginTransaction method is used to start a new transaction, sMgr.commitTransaction commits all changes to the Docbases and ends the transaction lock. In case of an error, sMgr.abortTransaction is used as a rollback to reverse any changes made so far in the transaction. You must call getSession AFTER beginTransacion or the session object will not be able to participate in the transaction. Use the isTransactionActive method to ask whether a "managed transaction" has already begun and the session manager currently has a transaction active that you can join. (You would not want to interfere with an outer transaction by blindly attempting to start a nested transaction, which is not allowed). The implementation of the transaction mechanism handles the following issues: With multiple threads, transaction handling operates on the current thread only. For example, if there is an existing DFC session for one thread, a new DFC session is created for the second thread automatically. This also means it is not possible to begin a transaction in one thread and commit it in a second thread. The transaction mechanism guarantees that the Session Manager provides a separate DFC session for each thread that calls beginTransaction. For those threads that already have a DFC session before the transaction begins a transaction, a new DFC session is provided and required to be used once beginTransaction is called. When a client starts a transaction using the sMgr.beginTransaction method, the Session Manager will not allow any other DFC-based transactions to occur (neither session.beginTrans nor sMgr.beginTransaction). It is not possible to nest transactions.

124

Developing DFC Applications

Using and Deploying Business Objects

The following example illustrates a client application calling two services that must be inside a transaction in which case both calls must succeed or nothing is done:
IDfClient client = DfClient.getLocalClient(); IDfSessionManager sMgr = client.newSessionManager(); sMgr.setIdentity(docbase, loginInfo); IMyService1 s1 = (IMyService1) client.newService(IMyService1.class.getName(), sMgr); IMyService2 s2 = (IMyService2) client.newService(IMyService2.class.getName(), sMgr); s1.setDocbase( strDocbase1 ); s2.setDocbase( strDocbase2 ) ; sMgr.beginTransaction(); try { s1.doDocbaseUpdate(); s2.doDocbaseUpdate(); sMgr.commitTransaction(); } catch (Exception e) { sMgr.abortTransaction(); }

If either of these service methods throws and exception, commit is bypassed and abort is executed. Each of the doDocbaseUpdate methods call sMgr.getSession. An interesting point to note in the above example is that the two services are updating different Docbases. The session manager, internally, automatically handles the real sessions and their real Docbase transactions (which translate to RDBMS transactions). Since the session manager is aware of all these Docbase handles within its own scope, committing or aborting the managed transaction causes the session manager to loop through its real session list and commit or abort those. The session manage supports transactions in this manner across multiple Docbases. However, if, for example, there are three Docbases, and the first two commit successfully, but the third does not update correctly during its commit, the session manager will not be able to undo the already committed transactions on those Docbases. Doing so would be a "two-phased commit" and is not supported by DFC.

Client Control
Client Control is a mechanism used to control how the session manager handles session pooling. Session manager sessions are managed by the session manager object. The client application is not able to directly control the lifetime of those sessions. (There are no methods to increase or decrease the timeout). All it can do is to set the identity and then either authenticate immediately or leave it to the service methods to obtain a session for a given Docbase.

Developing DFC Applications

125

Using and Deploying Business Objects

The client can control the session pool indirectly using either the transaction mechanism (that locks the session from being recycled to the session pool until commit or abort) or the "Client Control" mechanism (using the beginClientControl and endClientControl methods). As long as a transaction is active or the session pool is locked, the session is not recycled. For transaction management this is required because a transaction cannot work across different sessions. Client control is needed when you need to prevent the session manager from recycling and disconnecting a session that is still in use even if the service has already released the session. A typical scenario for client pool locking is when a service that is called returns a typed DFC object (for example, IDfCollection) which needs to be manipulated by its caller. DFC persistent objects internally store a reference to the session with which they were fetched. If the session is still valid, the session can be reacquired directly from the object using the IDfPersistentObject.getSession method. You cannot always depend on this session with managed sessions. However, if you have a session manager, it is best to acquire the session from that For objects that will be used in this manner, there is a need to lock the session until the typed object is discarded. In this case, the sMgr.beginClientControl method is used prior to calling the service and accessing the DFC object. When the client application is finished with this object it must call the endClientControl method to re-enable session manager recycling. The following example shows a service call that returns a collection of objects to be displayed. Client Control is used to ensure that the session associated with the collection is not recycled while the object names are printed out:
IDfClient client = DfClient.getLocalClient(); IDfSessionManager sMgr = client.newSessionManager(); sMgr.setIdentity(docbase, loginInfo); IDfSession session = null; IMyService anyService = (IMyService) client.newService(IMyService.class.getName(), sMgr); sMgr.beginClientControl(); try { session = sMgr.getSession( strDocbase1 ); IDfCollection coll = anyService.getObjects(); while( coll.next() ) System.out.println( coll.getString("object_name") ); coll.close(); } finally { sMgr.release( session ); sMgr.endClientControl(); }

Note: Since you are required to guarantee that endClientControl is always called after calling beginClientControl, call endClientControl within a finally block. Additionally, when an exception is thrown while a call is open, you must make sure the session is released. Use the Java finally block to ensure the client application control is switched off when the client application is done or in the case of an exception.

126

Developing DFC Applications

Using and Deploying Business Objects

Calls to beginClientControl can also be nested as long as there is a matching endClientControl for each beginClientControl When a program performs a query or accesses an object, it currently requires that you obtain a session and apply that session to any subsequent calls requiring authentication and operations on a content server. This can pose a problem for middle-tier application servers involving the maintenance of that session information between HTTP requests. When a BOF service returns a persistent object, the session manager must maintain the session in case access to the object is needed. DFC 5.1 separates the dependency of persistent objects from a session. This involves a new method to the IDfTypedObject interface called setSessionManager. When the setSessionManager method is called, the entire object is fetched from the server and its attributes are cached on the Java side. This allows the session manager to use that same session for other operations on the application server. When modifications are made to the cached persistent object, they are made to the local cache. When the object is saved or checked back in, the session manager supplies a session for that operation. Use setSessionManager judiciously. Because a "fetch" of the entire object is performed in order to cache the object to the Java side, it could be very costly. This should only be considered when a BOF service object returns a persistent object. A new class, DfCollectionEx has been added for your convenience. The DfCollectionEx class can be used when returning a collection of typed objects from a service. DfCollectionEx locks the session until the collection is closed with the DfCollectionEx.close() method.

Statistics
For testing or performance tuning purposes, the session manager provides an interface for querying the special session manager state parameters such as reference counters, number of sessions, Docbases currently connected, etc. Specifically, use the sMgr.getStatisticsmethod to retrieve an IDfSessionManagerStatistics object that contains the state information. The statistics object takes a snapshot of the session manager internal data when getStatistics is called. This means that the data may not be accurate by the time you look examine the data. The IDfSessionManagerStatistics provides the following information: Session pooling mode (for example, enabled/disabled) Whether there are active sessions Get a list of all Docbase names that have active sessions or identities Get a list of all IDfLoginInfo identities for a given Docbase (passwords are removed) Get a list of all active DFC IDfSession objects for a given Docbase Get reference count for a given Docbase session object

Error Handling
There are different scenarios for error handling in session manager, including:

Developing DFC Applications

127

Using and Deploying Business Objects

Bad identity defined (user , password): When authenticate is called or a session is retrieved DfAuthenticationException is thrown. The server message text is passed to this exception and can be shown to the user.

No identity or principal defined: When the user is authenticated, DfIdentityException is thrown. The message stored in the exception contains the Docbase name to be authenticated against. Set identity is called twice: If an identity is already defined for a given Docbase, (DfServiceException) is thrown. To be sure always call hasIdentity and clearIdentity first. Cannot generate session for principal: This may happen if the principal support is not configured properly. In this case DfPrincipalException is thrown. All other problems: In this case either a DfServiceException is thrown or for severe programming errors a runtime error is produced. DfServiceException does not contain a detailed error message. Check the log file for debugging.

How to use a Business Object from WDK


Session management and user authentication are the biggest issues related to using BOF services from WDK. DFC provides session management via the IDfSessionManager interface. WDK wraps nearly all the IDfSessionManager methods in the WDK SessionManagerHttpBinding class and the IDocbaseAuth and IDocbaseAccess WDK interfaces. A WDK Component object always has an associated managed IDfSession object. From within any method of a WDK Component object, you can call any of the getDfSession methods listed in Table 81, page 128.
Table 81. WDK Component getDfSession methods getDfSession methods getDfSession getDfSession( REQUEST_LIFETIME ) getDfSession( REQUEST_COMPONENT_LIFETIME ) Description

The remainder of this section shows how to call an SBO from a WDK component. The sample service looks up the address of a customer in a phone book, given the customers name or phone number. The main parts of the example are: The ICustomer SBO. A JSP/HTML form to provide the user interface. A custom WDK form event handler to initiate the action.

The user interface form appears as shown in Figure 81, page 129.

128

Developing DFC Applications

Using and Deploying Business Objects

Figure 81. Customer Service User Interface WDK Form

Define an ICustomer service interface that extends IDfService and provides the methods as shown:
public interface ICustomer extends IDfService { IDfId getCustomerIdFromPhone(String docbase, String phone) throws DfServiceException; String[] getCustomerData(IDfId id, String[] attributes) throws DfServiceException; }

The getCustomerIdFromPhone method returns the object ID of a customer object. The getCustomerData method accepts a customer ID and returns selected customer data attributes. You can create a JSP page as shown in Figure 81, page 129. The form uses a WDK form class named CustomerForm. The CustomerFormNls class handles button and text field labels. A properties file defines the configuration of these classes. Java constants defined in the CustomerFormNls class help you specify these resources. For example, the ID_PHONE constant maps to the value of a number configured in a properties file. The JSP form layout is CustomerForm.jsp. When a user presses the Lookup button, the onLookupPhone event method of CustomerForm runs.
<%@ page contentType="text/html; charset=UTF-8" %> <%@ page errorPage="/wdk/errorhandler.jsp" %> <%@ taglib uri="/WEB-INF/tlds/dmform_1_0.tld" prefix="dmf"%> <html> <head> <dmf:webform formclass="com.documentum.sample.customer.form.CustomerForm" nlsclass="com.documentum.sample.customer.form.CustomerFormNls"/> </head> <body> <dmf:form> <table> <tr> <td><dmf:label nlsid="ID_PHONE"/></td> <td> <dmf:text name="customer_phone"/> <dmf:button nlsid="ID_LOOKUP" onclick="onLookupPhone"/>

Developing DFC Applications

129

Using and Deploying Business Objects

</td> </tr> </table> <hr/> <table> <tr> <td><dmf:label nlsid="ID_NAME"/></td> <td><dmf:text name="customer_name"/></td> </tr> <tr> <td><dmf:label nlsid="ID_ADDRESS"/></td> <td><dmf:text name="customer_address"/></td> </tr> <tr> <td><dmf:label nlsid="ID_CITY"/></td> <td><dmf:text name="customer_city"/></td> </tr> </table> </dmf:form> </body> </html>

The onLookupPhone event method uses the ICustomer service to look up the customer information corresponding to the number. The method uses the SessionManagerHttpBinding WDK class to obtain a DFC session manager object prior to instantiating the service. The method casts the interface to the ICustomer type, so it can use that types methods. The implementations of the ICustomer methods use the Docbase name and the session manager objects to obtain and release a pooled session.
public void onLookupPhone( Button button, ArgumentList arg ) { Text textControl = (Text) this.getControl(PHONE); String phone = textControl.getValue(); String[] data = new String[0]; try { SessionManagerHttpBinding httpBinding = new SessionManagerHttpBinding(); IDfClient client = DfClient.getLocalClient(); ICustomer service = (ICustomer)client.newService( ICustomer.class.getName(), httpBinding.getSessionManager()); IDfId custId = service.getCustomerIdFromPhone( httpBinding.getCurrentDocbase(), phone); data = service.getCustomerData(custId, ATTRIBUTE_LIST); } catch( DfException e ) { WebComponentErrorService.getService().setNonFatalError( this, "MSG_CANNOT_GET_CUSTOMER", e ); } for( int i = 0; i < data.length; i++ ) { textControl = (Text) this.getControl(ATTRIBUTE_LIST[i]); textControl.setValue(data[i]); } }

130

Developing DFC Applications

Using and Deploying Business Objects

The code of the onLookupPhone method does the following: Obtain the phone number from the PHONE text box of the HTML form. Declare the String array data to receive the output of the getCustomerData method of the service. The getCustomerData method returns an array of string references, one for each customer attribute, in the same order as the fields are laid out. Construct a new WDK SessionManagerHttpBinding object. Use the getLocalClient factory method of the DfClient class to construct a local client. Note that you can call the getLocalClient method as many times as needed during an application without worrying about memory leakage, because it is a singleton. Use the SessionManagerHttpBinding objects getSessionManager method to obtain a session manager. Call the local clients newService factory method to obtain the ICustomer service object. The newService method uses DBOR to find and instantiate the Java class associated with the interface. The newService method takes the service name and a session manager reference as arguments. The method uses ICustomer.class.getName to obtain the fully qualified interface name. If you cannot import the service interface at development time, you must instead use a string like, com.documentum.services.customerservice. ICustomer. Call the getCustomerIdFromPhone and getCustomerData methods of the ICustomer interface to obtain the customer data. The method downcasts the DfService object that newService returns to the ICustomer interface, so it can call the two methods. The getCustomerIdFromPhone method returns the customer ID, which the getCustomerData method uses to retrieve the rest of the customers data attributes. Execute a for loop to iterate through the String array returned from the getCustomerData method and populate the HTML form fields with the customer data values.

How to use a Business Object from Visual Basic using IDispatch


The session manager is the key to using business objects from Visual Basic. To obtain a session manager object, use the following code excerpt as a template. While DFC and its methods are well known to the Visual Basic application using the TypLib, the interfaces of the individual BOF services are not known unless you go to the trouble to create your own Java/COM bridge for each service. The following excerpt demonstrates how to use the IDispatch interface mechanism to obtain a BOF service and call specific methods of that service. The main drawbacks of this approach are: Visual Basic does not provide a list of the method names available from the service.

Developing DFC Applications

131

Using and Deploying Business Objects

The code will not be type safe and can generate runtime errors that would not be detectable during compilation.
Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim clientx client loginInfo sMgr session service id custData() attrList() ctlText As As As As As As As As As As DfClientX IDfClient IDfLoginInfo IDfSessionManager IDfSession Object IDfId String String Text or use CreateObject( "Documentum.Dfc" )

Set clientx = New DFCLib.DfClientX Set client = clientx.getLocalClient Set sMgr = client.newSessionManager

Set service = client.newService("com.documentum.services.customer.ICustomer",_ sMgr ) attrList(0) attrList(1) attrList(2) attrList(3) = = = = "phone" "name" "address" "city"

Set id = service.getCustomerIdFromPhone( strDocbaseName, strPhone ) Set custData = service.getCustomerData( id, attrList ) ctlPhone = custData(0) ctlName = custData(1) ctlAddress = custData(2) ctlCity = custData(3)

Deploying Business Objects


Overview
Once a new business object (TBO or SBO) is developed and tested, it needs to be deployed into a production environment at some point. This environment may be a web application server or a client server application such as Documentum Desktop Client. BOF was designed to support both environments. This chapter describes how to deploy SBO and TBO into these different environments. In addition, it discusses what the different parts to be shipped are as well as how to design an installer to deploy to different environments.

Packaging
Each Business object (TBO or SBO) comes with a minimum of two Java class files. These are the business object interface and the Java implementation of that interface. These two

132

Developing DFC Applications

Using and Deploying Business Objects

Java class files must be accessible through the Java CLASSPATH from the JVM that will load and execute business object class files. Each business object requires an entry in DBOR on every computer that runs the application. This entry must match the Java classes installed. DBOR is located in a directory referenced by the DFC_DATA environment variable. In other words, when a TBO or SBO is deployed we not only need to copy the Java classes but also make sure DBOR matches the deployed components. DFC Version 5.1 or later is required to be able to run the SBO or TBO because DBOR registry is part of BOF, which is new with DFC Version 5.1. It is very important that the deployed business object Java classes of the TBO and SBO are accessed through the same Java class loader as DFC. This means that when running an application server that loads DFC through the CLASSPATH variable the deployed Java classes also need to be referenced by the CLASSPATH. However, when the application is deployed in a WAR file for an application server, the deployed Java classes for SBOs and TBOs must be located in the WAR file. The correct version of dfc.jar would need to be referenced in the CLASSPATH used by the application server servlet container, or supplied as a command line parameter when it is invoked. The rule is, either everything is referenced through the CLASSPATH, or everything is in the WAR file. Avoid mixing jar files. The dmcl40.dll file is excluded from this rule. It can be in a WAR file or referenced with the PATH variable. The WAR file DFC (dfc.jar) would then be located in WEB-INF/lib. If the deployed business objects are in a JAR file, this JAR file must be located in WEB-INF/lib. If the TBO and SBO class files are not shipped in a JAR file, they could also be located under WEB-INF/classes in the WAR file. In addition, client connection pooling should be enabled.

Packaging example
Assume that we want to deploy the IAutoNumber sample service, which consists of a several Java classes. These classes are shipped in a JAR file named autonumber.jar. The JAR file is built as follows (assuming a Windows server and default installation locations):
jar.exe -cvf autonumber.jar com com/ com/documentum/ com/documentum/services/ com/documentum/services/autonumber/ com/documentum/services/autonumber/AutoNumber.class com/documentum/services/autonumber/AutoNumberScheme.class com/documentum/services/autonumber/IAutoNumber.class com/documentum/services/autonumber/IAutoNumberScheme.class com/documentum/services/autonumber/INameGenerator.class com/documentum/services/autonumber/sample/ com/documentum/services/autonumber/sample/RunAutoNumber.class com/documentum/services/autonumber/UniqueNameException.class com/documentum/services/autonumber/Installer.class

Developing DFC Applications

133

Using and Deploying Business Objects

Business Object Registration


DBOR must be configured. Typically, dbor.properties file is located in the c:\Documentum\config directory. DFC is only able to locate this file in a subdirectory of the DFC_DATA directory, where DFC_DATA is usually set to C:\Documentum. DFC_DATA needs to be set as an environment variable or a Java system property. This environment variable is set up by the DFC installer. If, for some reason, you are not using the DFC installer this directory should be created and DFC_DATA should be defined as follows:
md c:\Documentum\config set DFC_DATA=c:\Documentum\config

In the DFC_DATA\config directory a properties file dbor.properties should have been created. If it does not yet exist then add the following two lines:
Table 82. DBOR Entry Attribute Samples For "service" And "type" com.documentum. services. autonumber. IAutoNumber dm_autonumber service com.documentum. services.autonumber. AutoNumber com.documentum. services.autonumber. AutoNumberScheme 1.0

type

1.0

DFC and BOF require the dfc.jar file. The DFC installer places it in the Documentum Shared files directory, (for example, c:\Program Files\Documentum\Shared). To make the services available to the application, servlet, or application server, copy the business object JAR file (for example, the autonumber.jar file created above) into a directory on your hard drive. There are several options for this and a few things to remember: Documentum tries not to impose restrictions on where these files can be located The files are loaded and executed by a JVM. All the rules governing the location, loading, securing, and executing the bytecode in the JAR files follows the rules and recommendations of Java. Considering the Java class loading algorithms and DFC requirements, we have determined that the following locations are good recommendations: Place your business object .JAR file in the JRE\lib\ext directory. This directory is known as the Java Extension Library. Files placed in this directory are implicitly scanned after rt.jar when the JVM searches for classes. Only after the JVM cant find a class in the bootclasses, then rt.jar, then the extension library, will it start to use the CLASSPATH variable. The downside to this approach is that this .jar file becomes visible to all Java applications on that computer. This is especially bad for DFC which contains libraries from Apache and Xerces. Those libraries contained in the dfc.jar file are not guaranteed to be the latest versions and a non-Documentum related application may break. Another problem is that IDEs, like IntelliJ, load all classes located in the JRE\lib\ext directory by default and can be overly time-consuming.

134

Developing DFC Applications

Using and Deploying Business Objects

A benefit of using the Java Extension Library is that the CLASSPATH environment variable is not used to locate your class. Another benefit is that the CLASSPATH variable is much shorter. There are a few drawbacks to using the extension library. If you install another JVM (for example, when you upgrade from 1.3.1_03 to 1.4.1), you would need to remember to copy all the JAR files from c:\Program Files\JavaSoft\JRE\1.3.1_03\lib\ext to c:\Program Files\JavaSoft\JRE\1.4.0_01\lib\ext. You need to choose a name for the .JAR file the does not conflict with a file already there. (Remember, the namespace is determined by the actual package names, like com.accelera.autonumber, not the name of the JAR file). Place your business object .JAR file in the any directory of your choosing - possibly a repository directory of business object .JAR files. Each Jar file would need to be added to the CLASSPATH variable. The CLASSPATH will begin to get very long. Place your business object .JAR file in the a WAR file in the WEB-INF\lib directory. The drawback here is that dfc.jar would also need to be located there. You must ensure that the CLASSPATH environment variable includes the JAR file of the new business objects, including dfc.jar. To be able to run DFC also the PATH environment variable has to be configured to the Documentum Shared directory where Documentum stores the shared libraries, DLLs and other necessary files. This is typically done by the DFC installer. If this is not the case the PATH variable has to be setup to reference dmcl40.dll for example located in c:\Program Files\Documentum\shared:
set PATH=c:\Program files\Documentum\Shared\;%PATH%

Now the Java application can be launched.

Documentation
When you develop a business object, you should also develop a set of Javadocs for it so that other developers (including yourself) may use it as a reference when calling the business object methods. Since Javadocs can be automatically generated from Java source code it tends to be very good for describing the details of an individual classes. Very often, however it is hard to get the overall picture. Try to give extended descriptions and overviews on what a business objects does and how it relates to other business objects for each class. The recommendation is to always ship Javadocs with a set of business objects.

Developing DFC Applications

135

Using and Deploying Business Objects

Custom Installer/Uninstaller
To write an installer that installs a Java application that uses TBOs and SBOs, there are several files to be copied to the target computer and DBOR must be configured.

AutoNumber Components
If you want to install the AutoNumber sample business object, follow these steps: Copy the autonumber.jar to %JAVA_HOME%\lib\ext Define the DFC_DATA environment variable. Create %DFC_DATA%\config\dbor.properties file and configure it as shown above.

136

Developing DFC Applications

Chapter 9 Overview of the DFC Interface Hierarchy

This chapter moves through the DFC interfaces that derive from the Documentum object type hierarchy, starting from the top. It contains the following major sections: Documentum Object Hierarchy, page 137 Typed Objects, page 142 Persistent Objects, page 146 Persistent Objects Without Associated Content, page 149 SysObjectsPersistent Objects With Content, page 152 IDfSession, page 154 IDfClient, page 159 Common Package, page 160

Documentum Object Hierarchy


Everything you manipulate in Documentum is an object. Documents, cabinets, folders, and even users are objects. Objects have associated characteristics called attributes (or properties), and associated operations called methods. Each object has a type, which is a template for objects of that kind. All objects of a given type have the same sets of attributes and methods. When the server creates an object, it uses the type description as a model. For example, document objects belong to the dm_document type. When you create a new document, the server uses the dm_document type description to create the new document object. The names of all system-defined type names begin with the prefix dm_. Attributes are fields that are part of the object. The values in these fields describe the object. For example, two of the attributes for a document object are title and subject. When you create a document, you provide a title and subject that are specific to that document. Attributes are either single-valued or multi-valued (repeating). Some are read only and some can be read or written. Using DFC, you operate on objects through interfaces that represent the object. Because the Documentum model and DFC are both object-oriented, a large part of the DFC structure corresponds directly to the Documentum object type structure. DFC provides

Developing DFC Applications

137

Overview of the DFC Interface Hierarchy

interfaces corresponding to most system-defined object types. The interface has separate set and get methods for each of the types attributes, and it has methods that pertain to objects of that type. You read or change the attribute values via the get and set methods, and you operate on the object through the interfaces methods. By the conventions of object-oriented programming, a method without arguments performs the corresponding operation on its associated object. For example, the statement
document.save();

appears in the example on Example 11, page 15. It tells the document object to apply its save method to itself, that is, to save the document in the Docbase. Methods that operate on other objects take references to those objects as arguments.

Subtypes and Supertypes


Documentum object types exist in a hierarchy. A supertype is an object type that is the basis for another object type, called a subtype. The subtype inherits the attributes of the supertype. The subtype can also have additional attributes of its own. Within the hierarchy, an object type can be a supertype, a subtype, both, or neither. For example, the dm_folder type is a subtype of dm_sysobject. It has all the attributes defined for dm_sysobject plus two defined specifically for dm_folder. A type can be both a supertype and a subtype. For example, dm_folder is a subtype of dm_sysobject and a supertype of dm_cabinet. Documentum lets you create your own object types. You can create a type with no supertype, defining all of its attributes yourself, or you can create a subtype of any of the following types: dm_sysobject and its subtypes dm_user and its subtypes dm_relation User-defined types

Persistence
Most objects the server manipulates are persistent, that is, they reside in the Docbase and persist across sessions. A document you create and save in one session is still there in another session on another day. Some objects are not persistent, that is, they do not reside in the Docbase. The server creates them as needed at runtime. For example, collection objects and query result objects, which return the results of DQL statements, are not persistent. When the server executes a DQL query it creates a collection object to contain the results of the query. It creates a query result object for each row that the underlying database returns for the underlying SELECT statement, and it associates the query result objects with the collection object. When you close a collection, the server destroys the collection object and the query result objects.

138

Developing DFC Applications

Overview of the DFC Interface Hierarchy

DFC Interface Hierarchy


DFC exposes most of the Documentum object hierarchy as a set of interfaces. An interface defines a contract between an implementation class and any client that uses instances of that class. Interfaces do not specify implementation. They simply define a set of methods with specific signatures and specific semantics. A class provides the implementation, but as an application programmer, you usually dont need to know which class. If you hold a reference to a class that implements a given interface, you know that objects of that class have all of the functionality that the interface promises. DFC includes a default implementation for each interface. For example, to operate on a document object, obtain an IDfDocument interface from DFC (this is an abbreviated way to say obtain an object that implements the IDfDocument interface). That interface allows you to read or set the objects attributes, attach content to the object, check the object into or out of a Docbase, and so forth. It doesnt matter whether the implementation class is DfDocument (DFCs default implementation of the IDfDocument interface) or another class that properly implements the functionality. By separating the implementation from the definition, interfaces isolate client code from changes in the underlying implementation. DFCs use of interfaces promotes customization, because it allows customers to substitute their own implementations for DFCs default implementations. DFC does not provide an interface for every server object type. Sometimes you must use the DFC interface that corresponds to a supertype of a given object type. For example, to write code to operate on cabinets, you must use IDfFolder (dm_folder is the parent, or supertype, of dm_cabinet). Some DFC interfaces correspond to operations that are independent of server object types. For example, the IDfLoginInfo interface, which allows you to assemble and maintain access information, does not correspond to a server object type. Another example is IDfPersistentObject. The IDfPersistentObject interface defines functionality common to all server objects that derive from dm_persistentobject. The type dm_persistentobject is the base type of all server objects that persist beyond the current session, but you cannot create a dm_persistentobject in the server, nor can you run a query that selects objects from the type dm_persistentobject. The server only allows the creation and querying of objects of types that are subtypes of dm_persistentobject. In DFC, on the other hand, IDfPersistentObject is a common type for arguments or return values. You can operate on a more derived type with a less-derived interface, but some methods are available only on more derived interfaces. For example, you cannot perform a save on the IDfTypedObject interface. To save, you must hold a reference to an IDfPersistentObject interface or an interface that derives from IDfPersistentObject. Similarly, to perform checkins and checkouts on an object whose type derives from dm_sysobject, you need to refer to that object with at least an IDfSysObject interface. A small subset of the Documentum object hierarchy appears in the following figure. DFC interfaces are in the top (white) parts of the boxes. The corresponding server objects are in the lower (gray) parts.

Developing DFC Applications

139

Overview of the DFC Interface Hierarchy

Figure 91. DFC Hierarchy Corresponds to Documentum Object Hierarchy

In Figure 92, page 141, you can see how the interfaces that derive from the Documentum hierarchy fit into the total DFC interface hierarchy.

140

Developing DFC Applications

Overview of the DFC Interface Hierarchy

Figure 92. DFC Interface Hierarchy

Developing DFC Applications

141

Overview of the DFC Interface Hierarchy

DFC interfaces that are not in the above diagrams are not part of the interface hierarchy. They do not derive from other DFC interfaces, and vice versa.

Typed Objects
The IDfTypedObject interface provides the basis for both persistent and non-persistent types. Here are the main facts about typed objects: They have attributes (properties) that you can retrieve and set. In almost all cases, you obtain them directly or indirectly through a DFC session; therefore they have a reference to the session that created them. A unique object ID identifies them.

The ID of a persistent object uniquely identifies the object in the Docbase. The ID of a non-persistent object, such as a collection or a Docbase map, identifies the object only for the session that creates it. The DFC online reference contains signatures of the methods of DFC interfaces (see Using the DFC Online Reference Documentation, page 20). This section describes the general categories of methods of the IdfTypedObject interface. IDfTypedObject is the base object for most DFC objects.

142

Developing DFC Applications

Overview of the DFC Interface Hierarchy

Session and Identifier


Typed objects have IDs, and they hold references to the session that created them. The IDfTypedObject methods getSession and getObjectId return this information.

Getting and Setting Attribute Values


An attribute of a Documentum object can contain either a single value or multiple values. An attribute that can have multiple values is called a repeating-value attribute or just a repeating attribute. Documentum defines the following types for attribute values: Boolean, Integer, String, ID, Time, and Double. The IDfTypedObject methods for setting and getting attribute values reflect these types. For single-valued attributes, call one of the following methods:
boolean getBoolean(String attrName) double getDouble(String attrName) IDfId getId(String attrName) int getInt(String attrName) String getString(String attrName) IDfTime getTime(String attrName) IDfValue getValue(String attrName)

The argument attrName refers to the attribute, such as object_name. Regardless of the type of the attribute, you can call getString to retrieve the value in the form of a string. If you call a get method that is inappropriate for the type of the attribute, for example, getInt("object_name"), DFC attempts to convert the value to that type. To set the value of a single-valued attribute, call one of the following methods, where attrName is the name of the attribute and value is the value you want to assign to that attribute:
void setBoolean(String attrName, boolean value) void setDouble(String attrName, double value) void setId(String attrName, IDfId value) void setInt(String attrName, int value) void setString(String attrName, String value) void setTime(String attrName, IDfTime value) void setValue(String attrName, IDfValue value)

There are several sets of methods that relate to repeating attributes. The server maintains an indexed array of values for a repeating attribute. For example, the authors attribute may contain the following values with the specified indexes:
[0] Sleepy [1] Dopey [2] Happy

Developing DFC Applications

143

Overview of the DFC Interface Hierarchy

[3] [4] [5] [6]

Sneezy Grumpy Doc Bashful

Methods that operate on repeating attributes often take an index, which specifies which value the operation should affect. The descriptions that follow refer to the authors listed above. The set and get methods for repeating attributes are similar to the set and get methods for single-valued attributes:
boolean getRepeatingBoolean(String attrName, int index) double getRepeatingDouble(String attrName, int index) IDfId getRepeatingId(String attrName, int index) int getRepeatingInt(String attrName, int index) String getRepeatingString(String attrName, int index) IDfTime getRepeatingTime(String attrName, int index) IDfValue getRepeatingValue(String attrName, int index) void setRepeatingBoolean( String attrName, int index, boolean value) void setRepeatingDouble( String attrName, int index, double value) void setRepeatingId( String attrName, int index, IDfId value) void setRepeatingInt( String attrName, int index, int value) void setRepeatingString( String attrName, int index, String value) void setRepeatingTime( String attrName, int index, IDfTime value) void setRepeatingValue( String attrName, int index, IDfValue value)

You can use single-value attribute methods to set/get repeating attributes and repeating-attribute methods to get/set single valued attributes. Single-valued methods always operate on the repeating attribute value at index 0. To use a repeating-attribute method for a single-valued attribute, the index argument must be 0. The call
getAllRepeatingStrings(String attrName, String separator)

returns all values of a repeating attribute as a single string with values delimited by separator, or by a comma if separator is null. For example, given the authors mentioned above,
getAllRepeatingStrings("authors", null)

returns the string


Sleepy,Dopey,Happy,Sneezy,Grumpy,Doc,Bashful

144

Developing DFC Applications

Overview of the DFC Interface Hierarchy

Additional Methods for Operating on Repeating Attributes


The following methods operate on repeating attributes. Type stands for Boolean, Double, Id, . . ., and datatype represents boolean, double, IDfId, . . . .
void appendType (String attrName, datatype value) void insertType (String attrName, int index, datatype value) int findType (String attrName, datatype value) int getValueCount (String attrName) void remove (String attrName, int index) void removeAll (String attrName) void truncate (String attrName, int index)

The appendType methods add values to the end of a repeating attributes list of values. For example, to add an eighth dwarf, call
myobj.appendString ("authors", "Burpy")

The insertType methods are similar, but they add the value at the specified index rather than at the end. To make Burpy the fourth dwarf, call
myobj.insertString ("authors", 3, "Burpy")

Generally, appending is more efficient, because insertions can force the server to copy existing values to new index locations. The find methods retrieve the first index at which a specified value appears. For example, findString ("authors", "Happy") returns 2. The remove method deletes the value at the specified index. The truncate method deletes all values from the specified index onward. The removeAll method deletes all values from the specified repeating attribute. The getValueCount method returns the number of values the specified repeating attribute has.

Attribute Information
IDfTypedObject has a number of methods that allow you to get information about the objects attributes:
String dump() int getAttrCount() boolean hasAttr(String attrName) boolean isAttrRepeating(String attrName) int getAttrDataType(String attrName) int findAttrIndex(String attrName) IDfAttr getAttr(int index) Enumeration enumAttrs()

The dump method is for debugging. It returns the objects attributes and values in a formatted string.

Developing DFC Applications

145

Overview of the DFC Interface Hierarchy

The getAttrCount method returns the number of attributes that the object has. The hasAttr method returns a boolean value indicating whether the objects type has the specified attribute. The isAttrRepeating method returns a boolean value indicating whether the specified attribute is repeating (True) or single (False). The getAttrDataType method returns an integer representing the attributes type (see the DFC online reference for IDfAttr for the possible return values). The attributes of a Documentum object have a column order. The findAttrIndex method returns the column index of the specified attribute. The getAttr and enumAttrs methods provide more detailed information about the specified attribute. The getAttr method returns an IDfAttr object for the attribute at the specified index. An IDfAttr object allows you to get the attributes name and type. IDfAttr also allows you to determine whether an attribute is repeating. If an attribute is of type String, the maximum character length of any value stored in that attribute may be obtained by calling IDfAttrs getLength method. The enumAttrs method returns an enumeration of IDfAttr objects. This enables you to iterate over all of the objects attributes.

Persistent Objects
Persistent objects are at the second level of the DFC interface hierarchy. They are typed objects that reside in the Docbase. The IDfPersistentObject interface inherits from the IDfTypedObject interface, and hence, IDfPersistentObject has all the methods of IDfTypedObject. In addition IDfPeristentObject has the following sets of methods.

Methods Relating to the Basic Properties of Persistent Objects


Every object in the Docbase has an i_vstamp attribute, which contains the number of committed transactions that have changed the object. This value is used for versioning, as part of the locking mechanism, to ensure that one user does not overwrite the changes made by another. The getVStamp method returns this value. You can replicate Documentum objects, that is, have them appear in more than one Docbase. The isReplica method returns True if the object is a local replica of an object in a remote Docbase. Every object in the Docbase has an object type. DFC exposes the type through the IDfType interface. To obtain an objects type information, call the getType method.

146

Developing DFC Applications

Overview of the DFC Interface Hierarchy

Basic Operations on an Object


IDfPersistentObject defines the following methods that affect or query the state of an object in the current session or in the Docbase:
void save() void destroy() boolean isDeleted() boolean isNew() boolean isDirty() void fetch() void revert()

The save method directs the server to store the local copy of the object into the Docbase. When you create a new Docbase object, others cannot see it until you explicitly call its save method. Saving an existing object fails if your version of the object is older than the object in the Docbase, that is, if the i_vstamp of your version contains a lower number than the i_vstamp of the object in the Docbase. This happens if another user saves changes to the object between the time you obtain a copy and the time you try to save it. You can prevent this from happening by checking out the object before changing it. The destroy method directs the server to remove the object from the Docbase. The isDeleted method tells you whether the object has been destroyed in the current session. This method does not detect deletion by another user or even in another session subsequent to the time that you obtained the local copy. The isNew method returns False if the object has ever been successfully saved in the Docbase. The isDirty method returns True if you have made unsaved changes to the local copy of the object. The fetch method obtains the latest version of the object from the Docbase if and only if the Docbase version has a newer i_vstamp. If the values are the same, the local copy retains any changes you have made. The revert method obtains the latest version of the object from the Docbase unconditionally. The local copy loses any changes you have made to it.

Audit Trail
Auditing enables you to record information about system events and preserve information in an audit trail, which you can then use to track events and generate reports. You choose which events to monitor, and the audit system logs pertinent data, including the time of the event. To support this process, IDfPersistentObject has the signoff method, which creates an audit trail entry of signoff information for an object.

Developing DFC Applications

147

Overview of the DFC Interface Hierarchy

Convenience Methods for Creating Object Relations


Documentum provides the dm_relation type to enable you to define relationships between objects. The IDfPersistentObject interface has methods that create a relationship between the persistent object and another persistent object specified as an argument. Other methods return information about the objects relationships (see the DFC online reference for more information):

IDfRelation addChildRelative( String relationTypeName, IDfId childId, String childLabel, boolean isPermanent, String d IDfRelation addParentRelative( String relationTypeName, IDfId parentId, String childLabel, boolean isPermanent, String void removeChildRelative( String relationTypeName, IDfId childId, String childLabel) public void removeParentRelative( String relationTypeName, IDfId parentId, String childLabel) public IDfCollection getChildRelatives( String relationTypeName) public IDfCollection getParentRelatives( String relationTypeName)

Validation Methods
DFC provides the IDfValidator interface, which makes it easy to validate proposed new or changed attribute values against information in the data dictionary. Normally, you need to do this when you interact with a user to obtain the attribute values. A related interface, IDfValueAssistance, supports providing contitional value assistance in the user interface. The following method returns an IDfValidator object for the persistent object:
IDfValidator getValidator()

You can also obtain an IDfValidator interface for an IDfType object:


IDfValidator getValidator(IDfID policy, String state)

The IDfValidator interface provides a variety of utilities:


void validateAll(IDfProperties attrValues, boolean modifiedAttrsOnly) void validateAllAttrRules(IDfProperties attrValues, boolean modifiedAttrsOnly) void validateAllObjRules(IDfProperties attrValues) void validateAttrRules(String attrName, IDfList values, IDfProperties depAttrValues) IDfValueAssistance getValueAssistance(String attrName, IDfProperties depAttrValues) boolean hasValueAssistance(String attrName) IDfProperties getValueAssistanceDependencies(String attrName) void setMaxErrorBeforeStop(int stopAfterNumOfErrors) int getMaxErrorBeforeStop() String getWidgetType(int environment, String attrName) void setTimePattern(String timePattern)

148

Developing DFC Applications

Overview of the DFC Interface Hierarchy

String getTimePattern() IDfPersistentObject getAssociatedObject() String getObjectType() IDfId getPolicyID() String getStateName()

Pass-Through Methods to the DMCL API


IDfPersistentObject provides methods that invoke the DMCL dmAPIGet, dmAPISet, and dmAPIExec methods. These IDfPersistentObject methods automatically insert the session ID and the object ID in the appropriate places. Use these methods only where necessary, that is, to access functionality that is not available via DFC. Calling these methods bypasses built-in support for validation:
String apiGet(String cmd, String args) boolean apiSet(String cmd, String args, String value) boolean apiExec(String cmd, String args)

Persistent Objects Without Associated Content


The level of the object hierarchy below IDfPersistentObject contains IDfSysObject, which is the root type for all objects that have associated content. Most user types extend IDfSysObject. Discussion of IDfSysObject appears in a subsequent section The other types at the level of the object hierarchy below IDfPersistentObject relate to the administration and operation of the Docbase. The following sections discuss these types.

IDfACL
IDfACL provides the functionality associated with the server type dm_acl. An access control list (ACL), also called a permission set, is the usual server mechanism for controlling who has access to an object. If the Docbase security mode is set to acl, then every sysobject (that is, every object of type dm_sysobject or of a type that derives from dm_sysobject) has an associated ACL that specifies which users can operate on an object and what they can do. The Documentum Content Server Fundamentals manual discusses the two kinds of permissions: basic and extended. Chapter 5, Using Validation and ACLs contains an extended example of how to use DFC to work with these permissions.

Developing DFC Applications

149

Overview of the DFC Interface Hierarchy

IDfFormat
IDfFormat provides the interface methods for obtaining the attribute information from a dm_format object. A format object contains information about a file format recognized by the server. All content stored in the Docbase has an associated format such as msw8 (Microsoft Word 97 document), pdf (Acrobat PDF document), or html (an HTML file). All sysobjects that have associated content keep the content type in the a_content_type attribute. This value corresponds to a dm_format object. Administrators can create new format objects for formats that the server does not support automatically. Format objects provide the information necessary to open a viewer or editor appropriate to the content type.

IDfUser and IDfGroup


The server documentation contains information about how to work with users and groups. Refer to the DFC online reference for details of the IDfUser and IDfGroup interfaces and their methods.

IDfType
IDfType provides methods for getting information about a type. IDfType provides the following categories of information.

Basic Attributes
The getName method returns the types namea string like dm_format or dm_document. The getDescription method returns the types user-friendly name from the data dictionary. The user interface uses the user-friendly name. For example, a search dialog box may display the name Format rather than dm_format.

Parent Type Information


Most types derive from other types. Firms that deploy Documentum usually create several layers of new types to meet their specific needs. IDfType provides the following methods to test whether the type derives from another type:
String getSuperName() IDfType getSuperType() boolean isSubTypeOf(String typeName)

150

Developing DFC Applications

Overview of the DFC Interface Hierarchy

The getSuperName method returns the name of the types parent type, or null if the type has no parent type. For example, if you hold an IDfType reference to the dm_document type, getSuperName returns dm_sysobject. The method getSuperType returns an IDfType reference to the supertype. You can call isSubTypeOf to test whether a type is a subtype of another type. For example, if you hold an IDfType reference to the dm_document type, isSubTypeOf("dm_sysobject") returns True. By convention, a type is not a subtype of itself, so isSubTypeOf("dm_document") returns False.

Type Information
Programs typically make use of IDfType objects to get information about the attributes of that type. The type dm_type contains several repeating attributes that describe the attributes of the type. The DFC methods for most of these attributes come in two varieties. One takes an index into the array of repeating attributes; the other takes a string specifying the attribute name. The indexed methods are slightly more efficient. The following IDfType methods return type information:
int getTypeAttrCount() String getTypeAttrNameAt(int index) int getTypeAttrDataTypeAt(int index) int getTypeAttrDataType(String attrName) boolean isTypeAttrRepeatingAt(int index) boolean isTypeAttrRepeating(String attrName) int getTypeAttrLengthAt(int index) int getTypeAttrLength(String attrName) int findTypeAttrIndex(String attrName) String getTypeAttrDescriptionAt(int index) String getTypeAttrDescription(String attrName)

The getTypeAttrCount method returns the number of attributes the type has. The method getTypeAttrNameAt returns the attribute name at the specified index. To find an attributes index, call findTypeAttrIndex. The indexes start at zero. The above get type attribute methods return the type of the attribute. This is one of the following values:
IDfType.DF_BOOLEAN IDfType.DF_INTEGER IDfType.DF_STRING IDfType.DF_ID IDfType.DF_TIME IDfType.DF_DOUBLE IDfType.DF_UNDEFINED

They return IDfType.DF_UNDEFINED only in unusual circumstances. The isRepeating methods indicate whether the attribute is repeating.

Developing DFC Applications

151

Overview of the DFC Interface Hierarchy

For attributes whose type is DF_STRING, the getTypeAttrLengthAt and getTypeAttrLengthAt methods return the maximum character length of any string that can be stored in that attribute. For attributes of other types, these methods return 0. The get type attribute description methods return attribute descriptions from the data dictionary. This information does not reside in the dm_type object. Recall that IDfType derives from IDfPersistentObject, which, in turn, derives from IDfTypedObject. IDfTypedObject has the following methods:
Enumeration enumAttrs() int findAttrIndex(String attrName) IDfAttr getAttr(int index) int getAttrCount() int getAttrDataType(String attrName) boolean hasAttr(String attrName) isAttrRepeating(String attrName)

Developers often find this confusing. Calling these methods on an IDfType object returns information about the attributes of the type dm_type, not the type that the IDfType object describes. For example, suppose that the IDfType object named doctype describes the type dm_document. The method doctype.getAttrCount returns 15, even though dm_document has almost 70 attributes. The reason is that getAttrCount returns the number of attributes that dm_type has, not the number of attributes that dm_document has. To get the number attributes for dm_document, call
doctype.getTypeAttrCount

Similarly, if you call doctype.getAttrDataType("object_name"), DFC throws an exception, because dm_type does not have an attribute called "object_name". To discover the type of the dm_document attribute object_name, call getTypeAttrDataType("object_name"). All IDfType methods that return attribute information about the type that the IDfType object describes have method names that begin with getTypeAttr. The methods inherited from IDfTypedObject return information about dm_type.

SysObjectsPersistent Objects With Content


IDfSysObject provides the functionality associated with sysobjects, that is, objects of the type dm_sysobject. Sysobjects can do the following: Own content. Be checked into and out of the Docbase. Have an ACL to control access. Reside in a folder. Be versioned. Be part of a virtual document.

152

Developing DFC Applications

Overview of the DFC Interface Hierarchy

Have an attached business policy (document lifecycle).

Types that need any of these capabilities derive from dm_sysobject. Since the primary focus of Docbases is content, most objects in the Docbase are either SysObjects or objects whose type derives from dm_sysobject.

Basic Operations on SysObjects


The IDfSysObject interface has a large number of methods. Some of these methods perform the same basic functions as correspondingly named methods in the operations package. In general, you should always use the version from the operations package. Refer to the DFC online reference for detailed information. The Documentum eContent Server Fundamentals manual provides the conceptual background. The following functional categories provide an overview of IDfSysObject: Checkout/Checkin These methods are mainly for internal use. See Chapter 2, Working With Documents, for the correct way to perform these tasks. Content-Related The Content Server Fundamentals manual discusses content, renditions, and file formats. Versioning Documentum provides implicit versions, major and minor version changes, version labels, and branching.Security Documentum provides two kinds of permissions: basic and extended. A user can have one basic permission level, and each basic permission level includes the capabilities of all of the lower levels. Users can also have any combination of the extended permissions. Using Private ACLs, page 64 and ACL Utility Methods, page 65 contain examples of how to use DFC to work with basic and extended permissions. Folder-Related Documentum provides folder and cabinet objects to organize the contents of a Docbase. All SysObjects and SysObject subtypes (except cabinets) must reside in a cabinet or in a folder. Virtual Document A virtual document is a compound document whose components are either simple documents or other virtual documents. The content that users see is the content files associated with these components. A virtual document can also have its own associated content file (or files). The components of virtual documents can have a mixture of formats. Business Policy Business policies are also known as document lifecycles (DLCs). The Documentum Content Server Fundamentals manual explains how DLCs work.

Developing DFC Applications

153

Overview of the DFC Interface Hierarchy

Types That Derive From IDfSysObject


An IDfDocument object contains information about a document. Documents can be simple documents or virtual documents. In a simple document, the content generally seen by a user is in one or more content files associated with the document. IDfDocument is a logical interface for operating on documents, but it does not add attributes or methods to those found in IDfSysObject. Documentum provides a folder and cabinet paradigm for organizing the documents in a Docbase. Cabinet objects are top-level folders and cannot reside in other folders or cabinets. A folder must reside in a cabinet or in another folder. DFC does not provide an IDfCabinet interface, so use an IDfFolder interface to operate on cabinet references. The dm_cabinet type has an attribute is_private, which is not an attribute of dm_folder. To retrieve this value, call the getBoolean method inherited from IDfTypedObject. For example,
boolean bIsPrivate = myCabinet.getBoolean("is_private");

Folders and cabinets do not usually have associated content. They derive from IDfSysObject because folders use the ACL security mechanism. The preceding sections discuss all of the interfaces in , except for IDfDocbaseMap and IDfCollection. Discussion of those interfaces follows the discussion of the IDfSession and IDfClient interfaces.

IDfSession
All interaction with a Docbase occurs in a session, that is, using an IDfSession object. In broad terms, a session: Uses the underlying DMCL library to maintain a connection to a Docbase. Maintains the state of the interaction between an application and the Docbase. Caches information to increase performance. A session keeps track of the objects you fetch and change. It provides explicit and implicit transaction support. The underlying DMCL does most of this, but DFC also caches some information and maintains some state. Provides service methods for creating and fetching objects, performing administrative tasks, and obtaining session information.

An IDfSession provides the following categories of functionality.

Provide Information
The following methods ask for information that the session has access to:
IDfClient getClient(); IDfLoginInfo getLoginInfo() String getDBMSName()

154

Developing DFC Applications

Overview of the DFC Interface Hierarchy

String getDMCLSessionId() String getDocbaseId() String getDocbaseName() String getDocbaseOwnerName() String getLoginUserName() String getSecurityMode() String getServerVersion() String getSessionId() boolean isACLDocbase() boolean isAdopted() boolean isConnected() boolean isRemote() boolean isShared()

Note: Be careful not to write getRDBMSName for getDBMSName. The version without the Ris correct.

Create Objects and Obtain Object References


Developers sometimes ask why they cant create a new SysObject as follows:
obj = new DfSysObject;

The short answer is that all persistent objects reside in the Docbase, so you can create or fetch them only through a session. Programming with DFC, page 13 discusses this point in more detail. The getObject methods return IDfPersistentObject interfaces, because IDfPersistentObject is the most derived interface that is general to all of the possible return types. For example, getObject could return an IDfType, an IDfUser, an IDfDocument, or an IDfFolder (among other possibilities). The only interfaces common to those types are IDfTypedObject and IDfPersistentObject. IDfPersistentObject is the more derived. The effect of this is that Java code must provide an explicit cast. For example
IDfFormat format = (IDfFormat) mysession.getObjectByQualification ("dm_format where name = tex);

The following methods support creating objects and obtaining object references:
int getDefaultACL() IDfACL getACL(String aclDomain, String aclName) IDfFolder getFolderByPath(String folderPath) IDfFormat getFormat(String formatName) IDfGroup getGroup(String groupName) IDfId getIdByQualification(String qualification) IDfPersistentObject getObject(IDfId objectId) IDfPersistentObject getObjectByPath(String objectPath)

Developing DFC Applications

155

Overview of the DFC Interface Hierarchy

IDfPersistentObject getObjectByQualification( String qualification) IDfPersistentObject getObjectWithType( IDfId objectId, String objType, String className) DfPersistentObject newObject(String typeName) DfPersistentObject newObjectWithType( String typeName, String className) DfType getType(String typeName) DfTypedObject getTypeDescription( String typeName, String attribute, IDfId businessPolicyId, String state) DfUser getUser(String userName) DfUser getUserByOSName( String userOSName, String userOSDomain)

Configuration Information
The Content Server documentation discusses configuration objects (see the sections dealing with apiconfig, sessionconfig, and serverconfig). The IDfClient interface provides the following methods. They return typed objects, because they return configuration information, not Docbase objects.
IDfTypedObject getClientConfig() throws DfException; IDfTypedObject getConnectionConfig() IDfTypedObject getDocbaseConfig() IDfTypedObject getDocbrokerMap() IDfTypedObject getServerConfig() IDfTypedObject getServerMap(String DocbaseName) IDfTypedObject getSessionConfig()

Transaction Support
The following are the basic methods for managing transactions:
void abortTrans() void beginTrans() void commitTrans()

Docbase Scope
Docbase scope tells the server which Docbase a method applies to. In many cases this does not change; in other cases, the server can determine it by examining a method argument that conveys the scope implicitly. For example, if one of the methods arguments is an object ID, the server can determine the Docbase scope from the ID.

156

Developing DFC Applications

Overview of the DFC Interface Hierarchy

The following are the basic methods for managing Docbase scope when necessary:
String getDocbaseScope() String setDocbaseScope(String DocbaseName) String setDocbaseScopeById(IDfId objectId)

Multithreading Support
If more than one thread can access a session, you must take care to lock and unlock the session before using it. The following IDfSession methods provide this capability:
boolean lock(int timeoutInMsec); boolean unlock();

You can lock the session explicitly (calling a method of IDfSession) or implicitly (calling a method of IDfPersistentObject, because persistent objects hold a reference to a session). Generally, you should lock and unlock blocks of code. If you lock and unlock a session at too fine a granularity, performance suffers and you increase the chance of making a mistake. If you lock too big a chunk of code, you cause other threads to wait needlessly, also hurting performance. DFC does not enforce the locking mechanism on sessions, so a multithreaded application must be careful to lock and unlock the session. Failure to do so can cause crashes. The need to protect a session against concurrent access applies to both shared sessions and private sessions (sessions obtained through the newSession call), but you must be especially careful if you share sessions across components in a multithreaded environment. You dont need to lock and unlock a session if only one thread at a time can use it. Tip In Java you can use the finally statement to ensure that a thread releases its lock when it dies. Lock sessions during transactions to prevent synchronization problems.

API Calls
Occasionally, an application needs to interact directly with the sessions underlying DMCL programs in ways for which DFC does not provide interfaces. The following routines allow such interactions:
ByteArrayInputStream apiGetBytes( String cmd, String args, String buf, String buflen, int length) IDfCollection apply( String objId, String functionName, IDfList args, IDfList dataType, IDfList values) IDfCollection getLastCollection()

Developing DFC Applications

157

Overview of the DFC Interface Hierarchy

IDfList apiDesc(String api) String apiGet(String cmd, String args) String describe(String type, String objType) String getMessage(int severityLevel) boolean apiExec(String cmd, String args) boolean apiSet(String cmd, String args, String value) boolean apiSetBytes( String cmd, String args, ByteArrayOutputStream content) void traceDMCL(int level, String traceFile)

Inbox and Workflow


The Documentum Content Server Fundamentals manual explains the way workflow templates and workflows work. The following methods pertain to inboxes and workflows:
IDfCollection getTasks( String userName, int filter, String additionalAttributes, String orderBy) IDfId sendToDistributionList( IDfList toUsers, IDfList toGroups, String instructions, IDfList objectIDs, int priority, boolean endNotification) IDfWorkflowBuilder newWorkflowBuilder(IDfId processId) String resolveAlias(IDfId sysObject, String scopeAlias) void dequeue(IDfId stampId) IDfCollection getEvents() boolean hasEvents() IDfCollection getRunnableProcesses( String additionalAttributes)

Administration
The following methods support system administration:
IDfId archive( String predicate, String operatorName, int priority, boolean sendMail, IDfTime dueDate) IDfId restore( String predicate, String dumpFile, String operatorName, int priority, boolean sendMail, IDfTime dueDate) void changePassword(String oldPasswd, String newPasswd) void reInit(String serverConfigName) void reStart(String serverConfigName, boolean restartClient) void shutdown(boolean immediate, boolean deleteEntry)

158

Developing DFC Applications

Overview of the DFC Interface Hierarchy

Session State
The following methods enable you to control certain aspects of the session:
void disconnect() void flush(String flushType, String cacheKey) void flushCache(boolean discardChanged) void purgeLocalFiles() void setBatchHint(int batchSize)

Miscellaneous
IDfRelationType getRelationType(String relationName) IDfVersionTreeLabels getVersionTreeLabels(IDfId chronicleId) String getLoginTicket()

IDfClient
Most DFC programs start by obtaining an object that implements the IDfClient interface, through a call like the following:
IDfClient client = DfClient.getLocalClient();

The IDfClient object loads the DMCL shared library. Its main function is to create and share sessions, but programs also use IDfClient to get information about the available Docbases and to obtain certain DMCL configuration information. IDfClient also enables client programs to cache information.

Creating Sessions and Obtaining References to Existing Sessions


Many of the IDfClient methods for dealing with sessions are no longer the best ones to use. The code examples in describe the session management facility introduced with DFC 5.1.

Maps and Config Information


Client applications often present the user with a list of available Docbases. DFC returns this list through the IDfDocbaseMap interface, which is obtained by calling the IDfClient getDocbaseMap method. The IDfDocbaseMap interface provides methods for getting the number of Docbases in the list, the name of the Docbase at a specified index, a description of the Docbase at the specified index, and the version of the server at the

Developing DFC Applications

159

Overview of the DFC Interface Hierarchy

specified index. IDfClient also provides methods for obtaining a docbroker map (the list of docbrokers that you can access) and a server map (the servers that you can access). It returns these maps as IDfTypedObjects. Typical client applications do not need these maps. The server documentation provides more information about them under the headings Docbroker Locator and Server Locator. IDfClient allows you to obtain information about your general client configuration through the getClientConfig method. This client configuration object maps to the API Config object discussed in the server documentation. Through this object you can dynamically configure such things as your Docbroker, the maximum number of simultaneous sessions allowed, and the maximum number of open collections allowed. You should alter the default values only after reading the server administration documentation.

Service Methods
The IDfClient object provides an IDfProperties object for caching and sharing information within your application. An IDfProperties object is an object that allows you to store name-value pairs. The method
getContext(String contextId)

returns the properties object for the specified ID or creates a new one if one does not already exist. The method
removeContext(String contextId)

removes the specified properties object. Some applications share data within a session by using this object. In this case, they typically use the session ID returned by the IDfSession method getSessionId as the context ID. You should not use the DMCL session ID (for example, s0) for this purpose. Applications should be careful to remove the properties object associated with a session when they no longer use that session.

Common Package
The com.documentum.fc.common package contains interfaces that client programs sometimes find useful. DFC wraps IDs and Time values in IDfId and IDfTime objects. To get an ID as a string you can call either getId or toString (they return the same thing). IDfTime objects allow you to perform time format conversions. Both the IDfId and IDfTime interfaces provide convenience methods. The getValue method returns an IDfValue object, which contains not only the attributes value, but also its type. IDfValue objects are convenient when you need to store an attribute value as an object (such as inserting it into a Java hashtable), but later need to determine its type as well as its value.

160

Developing DFC Applications

Overview of the DFC Interface Hierarchy

Avoid calling getValue if you can, because creating an additional object and obtaining and storing the type information are needless overhead if you dont use those features.

Developing DFC Applications

161

Overview of the DFC Interface Hierarchy

162

Developing DFC Applications

Chapter 10 DFC and DMCL

This chapter assumes that you are familiar with the methods that previous Documentum client products use to access server capabilities. It explains DFC by relating it to those methods. It contains the following main sections: Relationship to DMCL, page 163 This section explains the relationship between DFC and the Documentum client library (DMCL). Calling DMCL Directly, page 165 This section describes a way to bypass DFC and to communicate with the server via DMCL. DMCL to DFC Correspondence, page 165 This section contains a table of DMCL methods and the corresponding DFC methods.

Relationship to DMCL
The Documentum client library, DMCL, is a library of procedures and functions that implement the server API. DFC implements the API and an additional layer of related business logic, as shown in the following figure. It does so through a set of interfaces that client programs can use to access DFC from Java or COM.
Figure 101. DFC Builds Business Logic Above DMCL

Using DFC differs from using DMCL in the following ways: DMCL communicates via strings of arguments and results. DFC creates objects that implement specified interfaces. DMCL reports errors via error messages. DFC uses the Java exception mechanism.

Example 101. Using DMCL to access the server

The following calls show the ways to use DMCL to access the server.

Developing DFC Applications

163

DFC and DMCL

Pass DMCL a method (connect) and its arguments.


char *session = dmAPIGet("connect,docbase,user,password")

Pass the method (create), the session ID (s0), and the argument.
char *object = dmAPIGet("create,s0,dm_document")

Pass the method (get), the session ID (s0), the object ID (09017...), and the argument.
char *name = dmAPIGet("get,s0,09017...,object_name")

The following code illustrates DMCL error handling:


boolean fOK = dmAPIExec(checkout,s0, 09017...); if (fOK == FALSE) { char *err = dmAPIGet(getmessage,s0); dmAPIExec(reset,s0,09017...); }

DFCs IDfSession interface hides the session ID and object ID, leading to the following code corresponding to the first DMCL call:
IDfClient client = DfClient.getLocalClient(); IDfLoginInfo loginInfo = new DfLoginInfo(); loginInfo.setUser("user"); loginInfo.setPassword("password"); IDfSession session = client.newSession("docbase",loginInfo );

The second DMCL call corresponds to the following DFC code:


IDfDocument object = (IDfDocument)session.newObject("dm_document");

The third DMCL call can take either of the following forms with DFC:
String name = object.getString("object_name"); String name = object.getObjectName();

In the first form, you know that the attribute is a string. In the second form, you know that the object is of type dm_sysobject. If any of the DFC calls fails, DFC throws DfException, and the getMessage method of the exception object returns the same string that the DMCL getmessage method returns. DFC also performs the reset automatically. The following code fragments show how to handle the error: first in Java, then in Visual Basic:
try //Java { object.checkout(); } catch (DfException e) { // checkout failed System.out.println(e.getMessage()); } On Error GoTo errHandler #Visual Basic object.checkout GoTo finish errHandler: Dim e As IDfException Set e = cx.parseException(Err.Description) MsgBox e.getMessage finish:

The Visual Basic fragment assumes you have set cx via code like the following:
Dim cx as IDfClientX

164

Developing DFC Applications

DFC and DMCL

cx = CreateObject(Documentum.Dfc)

Calling DMCL Directly


This section describes a way to bypass DFC and access the server via DMCL. DFC provides complete, object-oriented access to the server API. Sometimes, such as when migrating legacy customizations, you may wish to call the server API directly. The following table describes DFC methods in the IDfSession interface that provide direct access to DMCL. Note: When you call DMCL directly, you bypass the DFC validation services. You must provide code to validate the data explicitly.
Table 101. Method apiGet apiSet apiExec Description Equivalent to calling dmAPIGet from DFC. Equivalent to calling dmAPISet from DFC. Equivalent to calling dmAPIExec from DFC.

Refer to the Content Server reference documentation for more information about how to use these methods. DFC returns a DfException object when a DMCL error occurs. In Java, use a try . . . catch code block to handle the error.

DMCL to DFC Correspondence


This section contains a table of DMCL methods and the corresponding DFC methods. The following table shows the DFC methods corresponding to DMCL API commands. If you are familiar with DMCL commands, use the table to find the corresponding DFC interface and method. The DFC column has format Interface :: Method.
Table 102. DFC Methods and DMCL API Commands DMCL Abort Acquire Addnote Addrendition DFC IDfSession :: abortTrans IDfRouter :: acquire IDfSysObject :: addNote IDfSysObject :: addRendition IDfSysObject :: addRenditionEx Anyevents IDfSession :: hasEvents

Developing DFC Applications

165

DFC and DMCL

DMCL Append

DFC IDfTypedObject :: appendBoolean d IDfTypedObject :: appendDouble IDfTypedObject :: appendI IDfTypedObject :: appendInt IDfTypedObject :: appendString IDfTypedObject :: appendTime IDfTypedObject :: appendValue

Appendcontent Appendfile Appendpart Appendtask Apply Archive Assemble Attach Begintran Bindfile Branch Changepassword Checkin

IDfSysObject :: appendContent IDfSysObject :: appendFile IDfSysObject :: appendPart IDfRouter :: appendTask IDfSession :: apply IDfSession :: archive IDfSysObject :: assemble IDfSysObject :: attachPolicy IDfSession :: beginTrans IDfSysObject :: bindFile IDfSysObject :: branch IDfSession :: changePassword IDfSysObject :: Checkin IDfSysObject :: CheckinEx

Checkinapp Checkout

IDfSysObject :: checkinApp IDfSysObject :: Checkout IDfSysObject :: CheckoutEx

Close Commit Connect

IDfCollection :: close IDfSession :: commitTrans IDfClient :: newSession IDfClient :: getSharedSession

Count Create

IDfTypedObject :: getAttrCount IDfSession :: newObject IDfSession :: newObjectWithType

166

Developing DFC Applications

DFC and DMCL

DMCL Datatype Demote Dequeue Describe Destroy Disassemble Disconnect Dump End Fetch

DFC IDfTypedObject :: getAttrDataType IDfSysObject :: demote IDfSession :: dequeue IDfSession :: describe IDfPersistentObject :: destroy IDfSysObject :: disassemble IDfSession :: disconnect IDfTypedObject :: dump IDfRouter :: end IDfPersistentObject :: fetch IDfSession :: getObject IDfSession :: getObjectWithType

Flush Flushcache Force Forward Freeze

IDfSession :: flush IDfSession :: flushCache IDfRouter :: force IDfRouter :: forward IDfSysObject :: freeze

Developing DFC Applications

167

DFC and DMCL

DMCL Get

DFC IDfTypedObject :: getBoolean IDfTypedObject :: getDouble IDfTypedObject :: getId IDfTypedObject :: getInt IDfTypedObject :: getTime IDfTypedObject :: getString IDfTypedObject :: getValue IDfTypedObject :: getAllRepeatingStrings IDfTypedObject :: getRepeatingBoolean IDfTypedObject :: getRepeatingDouble IDfTypedObject :: getRepeatingId IDfTypedObject :: getRepeatingInt IDfTypedObject :: getRepeatingString IDfTypedObject :: getRepeatingTime IDfTypedObject :: getRepeatingValue

Getcontent

IDfSysObject :: getContent IDfSysObject :: getContentEx

Getdocbasemap

IDfClient :: getDocbaseMap IDfClient :: getDocbaseMapEx

Getdocbrokermap

IDfClient :: getDocbrokerMap IDfClient :: getDocbrokerMapEx

Getevents Getfile

IDfSession :: getEvents IDfSysObject :: getFile IDfSysObject :: getFileEx

Getlastcoll Getlogin Getmessage

IDfSession :: getLastCollection IDfSession :: getLoginTicket This happens automatically when the error occurs IDfSession :: getMessage

168

Developing DFC Applications

DFC and DMCL

DMCL Getpath Getservermap

DFC IDfSysObject :: getPath IDfClient :: getServerMap IDfClient :: getServerMapEx

Grant

IDfACL :: grant IDfSysObject :: grant

Halt Id Insert

IDfRouter :: halt IDfSession :: getIdByQualification IDfTypedObject :: insertBoolean IDfTypedObject :: insertDouble IDfTypedObject :: insertId IDfTypedObject :: insertInt IDfTypedObject :: insertString IDfTypedObject :: insertTime IDfTypedObject :: insertValue

Insertcontent Insertfile Insertpart Inserttask Link Locate

IDfSysObject :: insertContent IDfSysObject :: insertFile IDfSysObject :: insertPart IDfRouter :: insertTask IDfSysObject :: link IDfTypedObject :: findBoolean IDfTypedObject :: findDouble IDfTypedObject :: findId IDfTypedObject :: findInt IDfTypedObject :: findString IDfTypedObject :: findTime IDfTypedObject :: findValue

Mark Next Offset Pause

IDfSysObject :: mark IDfCollection :: next IDfTypedObject :: findAttrIndex IDfRouter :: pause

Developing DFC Applications

169

DFC and DMCL

DMCL Print Promote Prune Purgelocal Query Queue Readquery Reassign Register Reinit Remove

DFC IDfSysObject :: print IDfSysObject :: promote IDfSysObject :: prune IDfSession :: purgeLocalFiles IDfQuery.execute IDfSysObject :: queue IDfQuery.execute IDfRouter :: reAssign IDfSysObject :: register IDfSession :: reInit IDfTypedObject :: remove IDfTypedObject :: removeAll

Removecontent Removenote Removepart Removerendition

IDfSysObject :: removeContent IDfSysObject :: removeNote IDfSysObject :: removePart IDfSysObject :: removeRendition IDfSysObject :: removeRenditionEx

Removetask Repeating Reset Restart Restore Resume

IDfRouter :: removeTask IDfTypedObject :: isAttrRepeating Happens automatically when the error occurs IDfSession :: reStart IDfSession :: restore IDfRouter :: resumeRouter IDfSysObject :: resume

Retrieve Reverse Revert

IDfSession :: getObjectByQualification IDfRouter :: reverse IDfPersistentObject :: revert IDfSysObject :: revertACL

Revoke

IDfACL :: revoke IDfSysObject :: revoke

Save

IDfPersistentObject :: save IDfSysObject :: saveLock

170

Developing DFC Applications

DFC and DMCL

DMCL Saveasnew Scope Set

DFC IDfSysObject :: saveAsNew IDfSession :: setDocbaseScope IDfTypedObject :: setBoolean IDfTypedObject :: setDouble IDfTypedObject :: setId IDfTypedObject :: setInt IDfTypedObject :: setString IDfTypedObject :: setTime IDfTypedObject :: setValue IDfTypedObject :: setRepeatingBoolean IDfTypedObject :: setRepeatingDouble IDfTypedObject :: setRepeatingId IDfTypedObject :: setRepeatingInt IDfTypedObject :: setRepeatingString IDfTypedObject :: setRepeatingTime IDfTypedObject :: setRepeatingValue

Setbatchhint Setcontent

IDfSession :: setBatchHint IDfSysObject :: setContent IDfSysObject :: setContentEx IDfSysObject :: setIsVirtualDocument IDfSysObject :: setFile IDfSysObject :: setFileEx

Setdoc Setfile

Setpath Shutdown Signoff Start Suspend Trace Truncate Type Unfreeze

IDfSysObject :: setPath IDfSession :: shutdown IDfRouter :: signOff IDfRouter :: start IDfSysObject :: suspend IDfSession :: traceDMCL IDfTypedObject :: truncate IDfSession :: getTypeDescription IDfSysObject :: unfreeze

Developing DFC Applications

171

DFC and DMCL

DMCL Unlink Unlock

DFC IDfSysObject :: unlink IDfSysObject :: cancelCheckout IDfSysObject :: cancelCheckoutEx

Unmark Unregister Updatepart Useacl Validate Values

IDfSysObject :: unmark IDfSysObject :: unRegister IDfSysObject :: updatePart IDfSysObject :: useACL IDfRouter :: validateRouter IDfTypedObject :: getValueCount

172

Developing DFC Applications

Index

A
abortTrans method, 156 ACLs, 62 private, 64 API calls, 157 to 158 API Config object, 160 apiDesc method, 158 apiExec method, 64, 158 apiGet method, 158 apiGetBytes method, 157 apiSet method, 64, 158 apiSetBytes method, 158 apply method, 157 archive method, 158

B
beginTrans method, 156

C
changePassword method, 158 close method, 56 collections stepping through, 57 com.documentum.com package, 19 com.documentum.fc.client package, 19 com.documentum.fc.common package, 19, 160 com.documentum.operations package, 19 com.documentum.registry package, 19 commitTrans method, 156 common.documentum.fc.client.qb package, 19 containment objects copy_child attribute, 22 copy_child attribute, 22

describe method, 158 DFC (Documentum foundation classes) comparison with DMCL, 165 datatypes, 17 DMCL process, 17 migrating to, 165 naming convention, 18 objects and pointers, 16 online reference, 20 server API callsx09, 165 DFC (Documentum Foundation Classes) COM interface, 13 elements, 13 DFC interface hierarchy, 140 DfClient class, 159 DfPersistentObject class, 156 DfQuery class, 55 DfType class, 156 DfTypedObject class, 156 DfUser class, 156 DfValidationException class, 61 disconnect method, 159 dm_cabinet type, 154 dm_folder type, 154 DMCL commands, 165 DMCL shared library, 159 Docbase scope, 156 docbrokers, 159 Documentum foundation classes. See DFC, 20 DQL queries, 55

E
enumAttrs method, 152 execute method, 57 External applications XML support, 22

D
dequeue method, 158

Developing DFC Applications

173

Index

F
findAttrIndex method, 152 flush method, 159 flushCache method, 159

G
getACL method, 155 getAllRepeatingStrings method, 144 getAttr method, 56, 152 getAttrCount method, 152 getAttrDataType method, 152 getBoolean method, 143, 154 getClient method, 154 getClientConfig method, 156, 160 getConnectionConfig method, 156 getContext method, 160 getDataType method, 56 getDBMSName method, 154 getDefaultACL method, 155 getDMCLSessionId method, 155 getDocbaseConfig method, 156 getDocbaseId method, 155 getDocbaseMap method, 159 getDocbaseName method, 155 getDocbaseOwnerName method, 155 getDocbaseScope method, 157 getDocbrokerMap method, 156 getDouble method, 143 getEvents method, 158 getFolderByPath method, 155 getFormat method, 155 getGroup method, 155 getId method, 143 getIdByQualification method, 155 getInt method, 143 getLastCollection method, 157 getLoginInfo method, 154 getLoginTicket method, 159 getLoginUserName method, 155 getMessage method, 158 getObject method, 155 getObjectByPath method, 155 getObjectByQualification method, 156 getObjectWithType method, 156 getQuery method, 55 getRDBMSName is incorrect, 155 getRelationType method IDfRelationType interface, 159 getRepeatingBoolean method, 144

getRepeatingDouble method, 144 getRepeatingId method, 144 getRepeatingInt method, 144 getRepeatingString method, 144 getRepeatingTime method, 144 getRepeatingValue method, 144 getRunnableProcesses method, 158 getSecurityMode method, 155 getServerConfig method, 156 getServerMap method, 156 getServerVersion method, 155 getSessionConfig method, 156 getSessionId method, 155 getString method, 56, 143 getTasks method, 158 getTime method, 143 getType method, 156 getTypeDescription method, 156 getTypedObject method, 56 getUser method, 156 getUserByOSName method, 156 getValue method, 143, 160 when to avoid, 160 getVersionTreeLabels method, 159 grant method, 62 to 63

H
hasAttr method, 152 hierarchy, of DFC interfaces, 140

I
IdfACL interface, 155 IDfAttr interface, 152 IDfClient interface, 14, 154, 156, 159 IDfClientX interface, 55 IDfCollection interface, 55 to 57, 157 to 158 IDfDocbaseMap interface, 159 IDfDocument interface, 154 IDfFolder interface, 155 IDfFormat interface, 155 IDfGroup interface, 155 IDfId interface, 143 to 144, 155, 158 IDfList interface, 158 IDfLoginInfo interface, 154 IDfPersistentObject interface, 139, 155 to 156 IDfProperties interface, 160 IDfSession interface, 14, 154, 157 IDfSysObject interface, 19, 152

174

Developing DFC Applications

Index

IDfTypedObject interface, 156 IDfValidator interface, 61 IDfValue interface, 160 IDfVersionTreeLabels interface, 159 IDfWorkflowBuilder interface, 158 IDfXMLTransformOperation, 39, 41 isACLDocbase method, 155 isAdopted method, 155 isAttrRepeating method, 152 isConnected method, 155 isRemote method, 155 isShared method, 155

N
newObjectWithType method, 156 newWorkflowBuilder method, 158

P
permissions, 62 to 63 persistent objects, 138, 155 private ACLs, 64 purgeLocalFiles method, 159

setDocbaseScope method, 157 setDocbaseScopeById method, 157 setDouble method, 143 setId method, 143 setInt method, 143 setRepeatingBoolean method, 144 setRepeatingDouble method, 144 setRepeatingId method, 144 setRepeatingInt method, 144 setRepeatingString method, 144 setRepeatingTime method, 144 setRepeatingValue method, 144 setString method, 143 setTime method, 143 setValue method, 143 shutdown method, 158 subtypes, 138 supertypes, 138 to 139 sysobjects, 152

T
traceDMCL method, 158 transactions, 156 transformations, 40 type libraries, 13 typed objects, 156

Q
queries, 56 to 57 displaying results, 57 flow of processing, 55

U
unlock method, 157

R
reInit method, 158 removeContext method, 160 repeating attributes, 145 resolveAlias method, 158 restore method, 158 revoke method, 63 rows, 56

V
validateAttrRules method, 62 virtual documents containment objects copy_child attribute, 22 copy behavior, defining, 22 defined, 21 purpose, 21 versioning, 22

S
save method, 64 sendToDistributionList method, 158 session ID, 41 sessions, 154, 159 multithreading, 157 setACL method, 64 setBatchHint method, 159 setBoolean method, 143

W
workflow templates, 158 workflows, 158

X
Xalan transformation engine, 39

Developing DFC Applications

175

Index

XML support, 22

XSLT stylesheets, 39

176

Developing DFC Applications

Você também pode gostar