You are on page 1of 98

Documentum Business Objects

Framework
Developer's Guide

DFC Version 5.1


August 30, 2002

Documentum Confidential and Proprietary Page 1 of 98


Copyright © 1999-2002
by Documentum, Inc.
6801 Koll Center Parkway
Pleasanton, CA 94566

All Rights Reserved. Documentum™, Documentum 4i™, Documentum e-Content


Server™, Documentum Desktop Client™, Documentum Intranet Client™, Documentum
WebPublisher™, Documentum RightSite®, Documentum Administrator™,
Documentum Developer Studio™, Documentum WebCache™, Documentum
ContentCaster™, AutoRender Pro™, Documentum Content Personalization Services™,
Documentum Site Delivery Services™, Documentum Content Authentication
Services™, Documentum DocControl Manager™, Documentum Corrective Action
Manager™, DocInput™, Documentum DocViewer™, Documentum DocPage Server®,
Documentum WorkSpace®, Documentum SmartSpace®, Documentum ViewSpace®,
and Documentum SiteSpace™ are trademarks of Documentum, Inc. in the United States
and other countries. All other company and product names are used for identification
purposes only and may be trademarks of their respective owners.

Documentum Confidential and Proprietary Page 2 of 98


Table of Contents
DOCUMENTUM BUSINESS OBJECTS FRAMEWORK.......................................... 1
TABLE OF CONTENTS ................................................................................................. 3
CHAPTER 1 INTRODUCTION........................................................................................... 1-1
Overview .................................................................................................................. 1-1
Business Objects in Perspective............................................................................... 1-2
CHAPTER 2 ARCHITECTURAL OVERVIEW ..................................................................... 2-1
DBOF Runtime Architecture.................................................................................... 2-1
Summary .................................................................................................................. 2-8
CHAPTER 3 DEVELOPING YOUR FIRST BUSINESS OBJECTS ........................................... 3-1
Getting Started with DBOF ..................................................................................... 3-1
Problem Scenario: Business-Wide Auto-numbering ............................................... 3-2
Solution: Documentum Business Objects ................................................................ 3-2
A Simple Type-based Object Example ..................................................................... 3-4
A Simple Service-based Object Example ............................................................... 3-21
CHAPTER 4 DOCUMENTUM BUSINESS OBJECT REGISTRY (DBOR) .............................. 4-1
Overview .................................................................................................................. 4-1
Architecture of the DBOR........................................................................................ 4-1
DBOR Usage - Runtime Object Lookup .................................................................. 4-4
DBOR Management ................................................................................................. 4-4
Error Handling ........................................................................................................ 4-7
CHAPTER 5 DBOF SESSION MANAGER ........................................................................ 5-1
Introduction.............................................................................................................. 5-1
Session Manager Features and Details ................................................................... 5-2
Managed Sessions.................................................................................................... 5-5
Authentication ........................................................................................................ 5-12
CHAPTER 6 SERVICE BASED BUSINESS OBJECTS .......................................................... 6-1
Introduction.............................................................................................................. 6-1
Architecture.............................................................................................................. 6-1
Rules and Guidelines (with examples)..................................................................... 6-2
CHAPTER 7 TYPE BASED BUSINESS OBJECTS................................................................ 7-1

Documentum Confidential and Proprietary Page 3 of 98


Introduction.............................................................................................................. 7-1
Architecture.............................................................................................................. 7-1
Implementation Rules, Guidelines, and Examples................................................... 7-3
Calling Rules, Guidelines, and Examples................................................................ 7-7
Error Handling ........................................................................................................ 7-8
Best Practices........................................................................................................... 7-8
CHAPTER 8 USING BUSINESS OBJECTS ......................................................................... 8-1
Overview .................................................................................................................. 8-1
How to use a Business Object from WDK ............................................................... 8-1
How to use a Business Object from Visual Basic using IDispatch.......................... 8-5
Guidelines and Best Practices ................................................................................. 8-6
CHAPTER 9 DEPLOYING BUSINESS OBJECTS ................................................................. 9-1
Overview .................................................................................................................. 9-1
Packaging ................................................................................................................ 9-1
Business Object Registration ................................................................................... 9-2
Documentation......................................................................................................... 9-4
Custom Installer / Uninstaller ................................................................................. 9-4
AutoName Components............................................................................................ 9-4

Documentum Confidential and Proprietary Page 4 of 98


Introduction Documentum Business Objects Framework (DBOF)

Chapter 1 Introduction
Documentum Business Objects Framework is a new framework for developing and
executing reusable business logic components. This framework is built in to the
Documentum DFC and accessible from applications written using DFC.
New to DFC Version 5.1, the Documentum Business Objects Framework (DBOF)
provides a framework and a methodology to develop reusable middleware server
components for business logic called Business Objects. This chapter introduces
Documentum Business Objects and the benefits this technology provides. It contains the
following major sections:
• "Overview " on page 1-1
• "Business Objects in Perspective" on page 1-2

Overview
The Documentum Business Objects Framework (DBOF) provides an object oriented
framework for building, testing, discovering, and deploying server business logic as
Business Objects. In addition, it provides a way for developers to hook their own logic
into normal DFC procedures by extending DFC classes.
DBOF lives wherever DFC lives, either on the Content Server or application servers, or
on any of the other clients.
DBOF is part of the DFC library and consists of several Java classes and interfaces for
constructing and running Documentum Business Objects (DBO) (see Figure 1-1). There
are two types of Documentum Business Objects, type-based business objects, and
service-based business objects. A type-based business object can extend a Documentum
Server persistent object type (e.g. "com_accelera_catalog" or
"com_accelera_autonumber" might extend "dm_document") and extend its capabilities
by providing new methods for those types (actually, new user defined Java classes) and
allowing overriding of existing methods, like save(), checkinEx() and checkoutEx().
A service-based business object provides methods that perform more generalized
procedures that are not usually bound to a specific object type or even Docbase.
The specific business logic within the business objects is implemented using the standard
DFC framework allowing developers to implement a new DBO without a steep learning
curve. Since DBOF objects are based on the Documentum Foundation Classes (DFC),
the developer can maintain a high degree of compatibility with existing DFC
applications.
This framework was designed to provide the ability to develop pluggable components,
each component implementing one or more middle-tier business rules. Figure 1-2 shows
a diagram of DFC and which parts of it are related to DBOF. Notice that the DBO
framework is implemented mostly in the DFC core layer. Custom business objects can
hook in and extend parts of DFC. In the future, DFC might implement some of its own

Documentum Confidential and Proprietary Page 1-1


Introduction Documentum Business Objects Framework (DBOF)

business objects. Service-based business objects can call into DFC, but are not
considered part of DFC.

Figure 1-1 DFC Provides DBO Framework


Service-based Business Objects
Other
Other Bus.
Bus. Obj.
Obj. Your
Your Bus.
Bus. Obj.
Obj. DCTM
DCTM Sample
Sample ISubscription
ISubscription Workflow
Workflow
Services
Services Services
Services Services
Services Services
Services Services
Services

Documentum Foundation Class Library (DFC)

DFC Intrinsic Future


Future Intrinsic
Intrinsic Objects
Objects Business
Business Objects
Extensions Objects
Type-based Operations High-Level
Business
Objects
Query Builder Workflow Validation Virtual Document Services
Layer
Other
Other Business
Business
Objects
Objects Core DFC Layer – Object oriented access to Server API Layer
Your
Your Business
Business
Objects
Objects DBO
DBO Framework
Framework fc.client Low-Level
Documentum
Documentum
Sample
Sample Objs
Objs

DFC to Server Access Layer


(Object-based access to Server API) Server Access

Business Objects in Perspective


A typical content rich Documentum application will be logically partitioned into layers
also referred to as "tiers". Each tier has a different responsibility in the overall
deployment, and within each tier, there can be one or more parts. The three main layers
in an n-tier model are the Presentation Layer, the Business Logic Layer, and the Data
Layer.

Documentum Confidential and Proprietary Page 1-2


Introduction Documentum Business Objects Framework (DBOF)

Figure 1-2 Documentum Business Objects N-Tier Model


Presentati on Layer
• Generic Components
• Custom Components
• Industry / Company specific behavior

Business Logic Layer


• Application Specific Abstraction
• Business Rules and Policies
• Common Object Model

Data Layer
Content and Data Schema
• Content Object Hierarchy
• Aggregated Business Data
• Common Schema

Core Content Management Services


• Library Services
• Process Automation
• Content Authentication

• Presentation Layer
The presentation layer contains components dealing with user interfaces and user
interaction. It is used to display content and structured information in a web browser
or stand alone application. For example, the presentation layer of a stand alone
application could be written in Visual Basic or Java Swing. In a web environment,
Documentum WDK would be the choice to present the layout and to manage the flow
and sequence of user interactions. The presentation layer consists of commercial or
custom UI components that display information in different ways depending on such
factors as the user role or their privileges. For most implementations, this layer is
highly customized and must be very configurable. 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 Layer
The business logic layer is completely independent of visualization and of the toolkit
used to display information. It provides application specific generalization as a layer
of abstraction and implements the customer specific business rules and policies. It is
based on a component object model with components shared between different
application areas. In most cases, the policies and procedures of a given company are
not very likely to change greatly so the business object components implement those
policies and procedures. Alternatively, if a policy or procedure does change, the
implementer can just modify the corresponding business logic component and all the
dependent applications and components will automatically conform to the new

Documentum Confidential and Proprietary Page 1-3


Introduction Documentum Business Objects Framework (DBOF)

policy. The business logic layer is the focus of the Documentum Business Objects
Framework described in this document.
One of the major improvements of Documentum 5.1 is the ability to support both
statefull and stateless Docbase sessions. This allows the business object to focus on
the business rules and to leave the session management and transaction handling to
the framework.
• Data Layer
The data layer is used by the business logic layer to permanently store the state of the
objects, content, and other information. Central to the data layer is one or more data
servers that house the stored state. The Documentum implementation of the data
layer is comprised of one or more eContent Servers with their associated RDBMS
servers. The data layer is logically separated into two useful parts, the Content and
Schema Layer and the Core Content Management Services Layer.
• Content and Data Schema Layer
The data schema layer defines the content object hierarchy as well as the physical
schema used to store the aggregated business data. Creation and management of
the schema can be achieved using the Documentum Administrator utility or
directly by using DFC calls. The business objects in the business object layer
provide a logical abstraction of the details of the DFC interfaces to the content
and data schema. Therefore, the business objects can manipulate content and its
metadata on behalf of the presentation layer applications without relying on those
applications being aware of how the data and content is physically organized.
Separation of the schema from the business logic layer and the database layer
promotes the ability to scale to a different database and continue to use the
business objects and applications unmodified.
• Core Content Management Services Layer
The core content management services layer provides the library services, process
automation, and content authentication to the business objects. This layer is
implemented by the Documentum eContent Server. It provides the basic building
blocks to construct higher-level business logic components.

Documentum Business Objects (DBO) Defined


Documentum Business Objects are designed to provide modular business logic to the
presentation layer by hiding the underlying Docbase schema and by using the core
services of the Documentum eContent Server. DBOs are either type-based or service
based:
• Type Based Objects (TBO)
Type based objects are implemented as classes that extend basic persistent DFC types
such as DfDocument, DfSysObject, DfPersistentObject, DfFolder, etc. They
allow you to encapsulate business logic that is specific to a particular Docbase object
type.

Documentum Confidential and Proprietary Page 1-4


Introduction Documentum Business Objects Framework (DBOF)

There are two main reasons for creating a TBO:


1. To provide a new behavior for new or existing custom object types. For instance, a
developer may decide to add getter and setter methods for object specific
attributes or add new methods like adding a Product to a Catalog TBO.
2. Customizing low-level operations to enforce data validations, referential integrity
and object specific business rules. For instance, a developer may decide to
override the save() and checkinEx() methods to be able to validate data before
saving them in the persistent storage.
• Service Based Objects (SBO)
Service based objects are not tied to a specific Documentum object type. They are
generalized objects that provide a specific service that may operate on different
Documentum object types or other business objects. An example of a service-based
object is the Documentum IInbox service that retrieves items from a user's inbox and
may also perform a number of other operations such as remove item, forward item,
etc. Such an object would not be tied to a specific object type. Your SBOs are built
using public DBOF interfaces and implementation classes supplied by DFC. Service
and session manager factory methods are also provided by DFC.

Benefits of using DBO


Faster development - DBO allows developers to reuse the business logic implemented
in existing components, shrink analysis time by using a predefined collection of business
logic components implemented in the business objects, and use the application expertise
captured in object sets. When applications are built by calling upon several business
objects services, the development time should decrease, as more of these components are
reused.
Protection of investment - DBO provides better portability and interoperability of
applications and Docbase model integrity, leverages work already done by Application
Servers, Web Services, etc., and facilitates application specific best practices and
standards.
Therefore, you should consider using Documentum Business Objects to implement
business logic that must:
• Be independent of visualization and of the toolkit used to display information,
• Be object oriented,
• Be modular, componentized, and highly reusable,
• Be compatible with existing code built using DFC.

Who will develop with Documentum Business Objects Framework?


Application developers who are familiar with Java and DFC can develop Documentum
Business Objects without a steep learning curve.

Documentum Confidential and Proprietary Page 1-5


Architectural Overview Documentum Business Objects Framework (DBOF)

Chapter 2 Architectural Overview


This chapter provides a detailed overview of the architecture of the new Documentum
framework for developing Documentum Business Objects, called Documentum Business
Objects Framework (DBOF).
With DFC 5.1 and above, DFC includes a new framework for developing and executing
reusable business logic components. This new framework is built in to the Documentum
DFC and accessible from applications written using DFC.
Using this framework, you can write new content management services that can be
plugged into applications. In addition, services can call upon other services and benefit
from their implementation of other business rules. The changes to DFC that provide
Business Objects support are compatible with existing applications.

DBOF Runtime Architecture


Develop a Documentum business object to implement some business logic for content
management related activities. While service based objects can be designed to perform
tasks not related to Docbase activities, the framework was designed with middle-tier
content management support in mind and will be the focus of this manual.
The following DFC elements are those that were designed to provide runtime DBO
support.
• Core DFC support for DBOF
• Object Factory Guarantee
• Accessing Business Objects
• Session Manager
• Session Pooling
• Session Transaction Processing
• DBOR
• Business Objects Class Hierarchy

Core DFC support for DBOF


The DBOF framework is integrated into the DFC core. This guarantees that everyone
will access the business objects the same way. The DFC core integrates at a fundamental
level the object factory and the object registry. It also supplies a session manager and
principal support. The sections of this chapter describe these new elements of DFC and
where they fit into the architecture of the DBOF.

Documentum Confidential and Proprietary Page 2-1


Architectural Overview Documentum Business Objects Framework (DBOF)

Object Factory Guarantee


The DFC 5.1 object factory guarantees the correct object will be constructed at runtime.
This applies to Type based Business Objects, but not necessarily to Service-based
Business Objects. The following paragraphs describe how this mechanism works with
regular Docbase objects as well as TBOs, which are extensions of those types.
Documentum Business Objects Framework also allows you to extend certain existing
DFC classes using Type based Business Objects, allowing you to enhance the behavior of
existing methods, replacing them altogether, and even adding new methods. When a
Type based business object (TBO) is developed and deployed on your system, the
framework guarantees that all software accessing this object through previous means will
now obtain the new extended object. For example, when a servlet obtains an object using
the session.getObjectByQualification() method, the object is fetched from the
Docbase. This has always been one of the hallmark features of the Documentum
repository. For example, if the FROM clause of a query specifies dm_sysobject, but the
WHERE clause indicates instances of your new custom Docbase types, the Documentum
system has always been able to automatically fetch the custom subtype. However, the
DFC system would construct an instance of the DfSysObject, DfDocument, and so on,
limiting the functionality to the methods supplied by those standard DFC classes.
With TBOs, you are not limited to the methods and behaviors provided by the standard
DFC classes. You can supply your own class, as a subclass of the DFC class. In this
case, DFC dynamically constructs an instance of the new subclass at runtime. Even when
accessed by programs unaware of the new subclass.
When the aforementioned servlet calls methods like checkout() and save(), and these
methods are overridden by the business object tied to this type, the overridden methods
are called instead. Through an object oriented mechanism, called polymorphism, the
checkout() and save() methods are searched for in a bottom-up order, executing the first
one that matches. If the new type overrides the save() method with new business logic,
such as validation logic, the new method will perform its new save() operation.
Two things make this possible. One is the Documentum Business Objects "Registry"
(DBOR). The other is that use of the registry is now an integral part of the DFC core.
Whenever someone attempts to access a custom-type Docbase object, DFC first checks
the registry for a mapping to a custom Java class, then loads and instantiates that class.
DFC version 4 did not perform this mapping. (This is one of the reasons you should not
use DFC 4 compliant clients with custom types that were designed for Version 5.1).
Figure 2-1 shows getting access to a Docbase object through a TBO after DFC has
checked with the DBOR as to which Java class to construct that represents the Docbase
subtype.

Documentum Confidential and Proprietary Page 2-2


Architectural Overview Documentum Business Objects Framework (DBOF)

Figure 2-1 - TBO Interaction Diagram


Client
ClientProgram
Program TB
O
ac
ce
ss

DFC fc.client Session Manager session


session
pool
pool

DBO Factory

Typed
Typed B.O.
B.O.

DBO
DBO
Registry
Registry
Docbase

Accessing Business Objects


Figure 2-2 shows a type based business object using another type based business object.
When this happens, the consumer is considered the "client".
Figure 2-2 Business Object using - another Business Object
TBO Client TB
O
ac
ce
ss

DFC fc.client Session Manager session


session
pool
pool

DBO Factory

Typed
Typed B.O.
B.O.

DBO
DBO
Registry
Registry
Docbase

Service based Business Objects (SBO)


Figure 2-2 shows how a service-based business object is different from the type based
business objects shown in Figure 2-1. Each service based business object provides a
generalized interface to a group of related operations that need to be performed. The
operations may not need access to a Docbase, however, content management services are
the focus of Documentum Business Objects. An SBO is obtained through the DFC

Documentum Confidential and Proprietary Page 2-3


Architectural Overview Documentum Business Objects Framework (DBOF)

IDfClient interface. When requesting access to a service, the IDfClient checks the DBO
Registry for the service name and instantiates its associated Java class. The interface
provides methods to the actual service that implements the business rules of the service.
SBOs can access objects across several Docbases and are usually implemented such that
they can be called by an application server component and the service can obtain and
release the Docbase sessions dynamically as needed.

Figure 2-3 - SBO Interaction Diagram


Client
Client Program
Program
s s
ce
ac
S BO
DFC
fc.client

DBO Factory

Service
Service B.O
B.O

DBO
DBO
Registry
Registry

Calling a Service based Object


At any level, a method of a business object can be called by other DFC based
applications. A WDK component can call an SBO service just as easily as any stand-
alone Java program could. JSP, ASP, Visual Basic, and other languages all have access
to the business objects.
Business Objects are considered "clients" when accessing other Business
Objects
The Java classes of the business object will be loaded and called by the DFC client
factory methods using class-mapping information obtained from the DBOR. DBOF
objects are a Java technology. Like all Java programs (with the exclusion of RMI), the
Java classes are loaded into the process address space of the JVM.
When any Java programs, including type-based objects, access a Documentum server in
this way, they too are clients, even if they are a service being called by another service.
What this means is, that when an SBO calls another SBO or another TBO, the interaction
between the clients, the DBOR, and the service classes load the same way as when a
stand-alone program loads them. That is to say, that when a TBO calls an SBO or
another TBO, it is treated like the client in Figure 2-1. Figure 2-4 shows a service based
business object calling another service based business object. The DBOR is used to
locate the Java class corresponding to the service name.

Documentum Confidential and Proprietary Page 2-4


Architectural Overview Documentum Business Objects Framework (DBOF)

Figure 2-4 - Any Business Object calling an SBO


Business
s
Object
s
ce
ac
O
DFC SB

fc.client

DBO Factory

Service
Service B.O
B.O

DBO
DBO
Registry
Registry

Remote Execution of Business Objects


Documentum Business Objects run in local mode only. They currently do not support
remote execution. Web Services and .NET could be two technologies the framework
supports in the future but currently it only supports local mode.
Clients can use business objects
DBOF was designed for use by different clients, including Java, WDK, Servlet, JSP,
Visual Basic, C++, and ASP. The current design, however, is that they are developed
only in Java and accessible via clients based on these various technologies. All the non-
Java clients currently use COM through the DFC 5.1 Documentum Java COM Bridge
(DJCB).

Session manager
Whenever an application acquires any access to a Docbase, authentication is required.
Another improvement supplied by DFC 5.1 is "managed sessions" using the session
manager. It encapsulates the DFC session object and automatically manages the session
pool. It also provides the transaction handling and authentication of multiple identities on
multiple Docbases. For reestablishing a managed session, the session manager can hold
several Docbase login "identities", one for each Docbase or a "principal" identity, an
identity used by the service to authenticate the service as if the service is that principal
identity. It also provides methods to get access to the DFC session handle and hooks to
manage a session pool for stateless operation. It manages access to multiple Docbases
and controls transaction processing across multiple services. For convenience to the web
programmer, it also provides methods to associate state with the session to make session
management more straightforward.
The main requirement for an SBO is for it to request a DFC session through the session
manager and to release it as soon as it no longer needs to access a Docbase. With TBOs,
a reference to the TBO's session is embedded inside the object by default. This session
may become invalid if the requesting method releases the pooled session. There is a
special case where the DFC session can be "separated" from the current DFC session and

Documentum Confidential and Proprietary Page 2-5


Architectural Overview Documentum Business Objects Framework (DBOF)

the TBO is put under session manager control. This is required in cases where a stateless
SBO creates a TBO, which is stateful, that is returned to the caller.

Session Pooling
Session pooling provides for an application to connect and disconnect from a Docbase
session many times without incurring the overhead of real sessions with the server. The
general idea is to release the session back to the session pool often when acting in a
stateless manner. The session manager does not disconnect the session with the server
when a client releases the session. Rather, the session is put back into the session pool,
free to be used by other requests for other sessions.

Session Transaction Processing


The DFC session manager provides "managed transactions" for "managed sessions".
When session pooling is used, it is theoretically possible that DFC sessions are pooled
between individual calls to services. Let’s say there are two services: the first service
creates a few folders and the second service stores some documents in these folders. To
make sure the folders are only created if the documents are successfully created, there
must be a transaction across the two service calls. The DFC transaction is bound to one
DFC session, therefore it is important to use the same DFC session when calling both
services. Each service performs its own atomic operation. At the beginning, they request
a DFC session, and at the end, they return this session back to the session pool. If any
errors occur during either operation, the transaction is aborted and all Docbase updates
since the beginning of the transaction are rolled back to their pre-transactional state.
The DFC 5.1 session manager provides several new methods that allow transaction
processing with stateless sessions. Using the session manager transactions, you can now
perform transaction processing across Docbases. (Two-phased commit is not supported
by the Docbase since not all RDBMS support two-phased commit, therefore, the DFC
supports single-phased commit.)

Documentum Business Objects Registry (DBOR)


The business object registry provides the following mapping at runtime:
• Docbase Type name to Java Class mapping
When the DFC core loads a Docbase object, its type name is looked up in the registry.
If the name is found, its corresponding Java class is loaded and instantiated.
• Service Interface name to Java Class mapping
When requesting the client to load a service, the service is identified by its published
interface name, such as com.documentum.IInbox. If DFC finds the interface name in
the registry, the corresponding service class is loaded and instantiated and returned to
the caller.

Documentum Confidential and Proprietary Page 2-6


Architectural Overview Documentum Business Objects Framework (DBOF)

Business Objects Class Hierarchy


Figure 2-5 shows a class diagram for a Service based Business Object. The Client object
represents the consumer of the IAutoName service. The IAutoName service interface is
implemented by the AutoName class. The IAutoName service interface has access to the
DfService object extended by its AutoName implementation. The client gains access to
the IAutoName service by using IDfClient to find the class mapping from the IDfDbor,
and then instantiates the AutoName object.
Figure 2-5 - Class Diagram for Service based Business Objects

Client

uses uses

IDfClient uses IDfSessionManager

creates uses
implements

IDfDbor IDfService DfSessionManager

uses
IAutoName

IDfPrincipalSupport extends
implements IDfSessMgrStatistics
uses
DfService implements
uses

AutoName

extends

Figure 2-6 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
IDfSession.getObject(), which causes the IDfClient of the framework to query the
DBOR registry for the class to instantiate.

Documentum Confidential and Proprietary Page 2-7


Architectural Overview Documentum Business Objects Framework (DBOF)

Figure 2-6 - Class Diagram for Type-based Business Objects


Client

uses

uses IDfSession IDfClient

uses

creates
uses

IProduct IDfBusinessObject IDfDBOR

extends

implements

Product DfSysObject DfPersistentObject DfTypeBasedObject

extends extends extends

Summary
When developing with Documentum Business Objects Framework, it is important to
understand that DBOF is built-in to DFC 5.1 and is an integral part of DFC. Remember
that DBOF was primarily designed to provide an environment for stateless access to
Docbase data from middle-tier business objects. You should do your best to use the
session manager and release sessions as soon as possible. You can rely on the session
manager to manage connections and transactions with the Docbases. Using DBOF, you
can implement business logic in reusable business object components that can be plugged
in to your middle-tier applications.

Documentum Confidential and Proprietary Page 2-8


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

Chapter 3 Developing Your First


Business Objects
This chapter steps developers through the process of creating both service and type-based
business objects (TBO) using a very simple example that illustrates the use of DBOF.
One of the purposes of creating a TBO at this point is to demonstrate the basic principle
of TBOs - that their Java class is automatically used whenever an object is accessed
through normal, already existing programs. For example, Documentum Desktop Client
and WDK will automatically start using the overridden methods of your extending class
without making any changes to Documentum Desktop Client or its configuration.
Remember, this will happen with Documentum 5.1systems.
The example used for the exercise is an auto-numbering service. The first section,
Getting Started with DBOF, guides you through the initial set up of DBOF. There are
two other sections; each including a test application designed as simple tutorial test case
applications. The Simple_TBO test application allows you to practice building,
deploying and testing a type based business object. The Simple_SBO test application
allows you to practice building, deploying and testing a service based business object
(SBO).
The Simple_xBO test applications are simplified examples of a real-world business
problem, that of maintaining a business-wide sequential numbering system for a variety
of purposes, like purchase orders, invoices, contract and application documents, and other
purposes. The example will be overly simplified so the Simple_xBO application will be
able to demonstrate the basic concepts of Documentum Business Objects without
creating too much confusion specific to that particular issue. A more fully functional
"AutoName" sample service ships with DFC 5.1.
This chapter contains the following main sections:
• "Getting Started with DBOF" on page 3-1.
• "A Simple Type-based Object Example" on page 3-4.
• "A Simple Service-based Object Example" on page 3-21.

Getting Started with DBOF


This is a step-by-step guide on initial setup required to have DBOF ready to use. Perform
the steps provided here before proceeding with the example exercise.
Be sure to perform the following steps before implementing the example:
1. Install DFC 5.1 on your client computer (i.e. Windows NT/2000/XP). Run the
DFC installer as described in the DFC installation manual. This also includes
setting up the Java runtime environment (JVM) on your client computer. Use Sun
JDK1.2 or later. You may also use a compatible JVM from other vendors that are
Java 1.2 compliant (or later). It is not possible to use the Microsoft JVM because
it doesn't support JDK 1.2.

Documentum Confidential and Proprietary Page 3-1


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

2. Setup a new Docbase or get access to an existing test Docbase.


3. Configure DMCL.INI to both access your test Docbase and enable session
pooling. For the latter, add the following entry to the [DMAPI_CONFIGURATION]
section: connect_pooling_enabled = T
4. Make sure you have a Java IDE installed. For example IntelliJ, Borland,
WebGain, IBM, etc.
5. Make sure (a) dfc.jar is referenced by the CLASSPATH environment variable of
your IDE or JVM running the application, and (b) dmcl40.dll is in a directory
referenced by the PATH variable. Both files are installed by default in
c:\Program Files\Documentum\shared. (The CLASSPATH should
also contain a reference to the jar file of your new Business Objects. Optionally,
you can place the files into your Java Standard Extension Library - "..\lib\ext")
If you are running from within and IDE, like IntelliJ or Forte', the IDE usually
requires additional CLASSPATH settings.
6. The DFC_DATA system variable must refer to the directory containing
Documentum configuration information, usually c:\Documentum. This needs to
be a directory that has an immediate subdirectory called c:\Documentum\config.
This is where the dbor.properties file is located. (Future best practices might
recommend using c:\Documentum\DFC_DATA\config)
Caution: The current implementation of the Documentum Business Objects Registry
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 as well as
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. You should not attempt to edit this file without using the DBOR
maintenance tool.

Problem Scenario: Business-Wide Auto-numbering


The Simple_TBO and Simple_SBO test applications are a simplified solution to a real-
world business problem, that of maintaining a business-wide sequential numbering
system for a variety of purposes, like purchase orders, invoices, and other purposes.
In order for a business to be able to supply a centralized numbering system for all the
employees who are performing similar tasks, the numeric value used to calculate the
"next number" must be stored in the system and all the employees would need to base
their numbering system on that number only. Locks are put into place to serialize access
to the number so that it safely increments sequentially.

Solution: Documentum Business Objects


This scenario divides the problem into two solutions.
1. Type-based business object (TBO), the subject of the Simple_TBO example,
provides the persistent storage. Use a Docbase as the central storage for the value

Documentum Confidential and Proprietary Page 3-2


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

used to calculate the next number. A new Docbase type will be created (e.g.
"com_accelera_autonumber" that is a subtype of dm_sysobject) that will have an
attribute, "current_number", storing the value of the last number generated as a seed
for the next number in that numbering type. (Note: Accelera.com is a fictitious
domain name of a fictitious conglomerate that Documentum created for
demonstration purposes.)
° In addition, a business rule might impose a restriction on the maximum value of a
number for a given numbering type, or that the number is zero-filled to a certain
number of digits.
° Different numbering sequences, like purchase orders and invoice numbers, would
need a separate storage for each sequence since it is usually not desirable for to
sequence numbers as, PO001, INV002, PO003, INV004.
° Additional rules might require that purchase order numbers are prefixed with "PO",
whereas invoice numbers begin with "INV". In this simple example, this will be
handled by the user of the IAutoNumber interface. A future subclass of the
autonumber type could handle as well.
° The application of these business rules and validation would need to be performed
each time the value for the "next number" would be calculated, stored, and
fetched. This is accomplished by overriding the methods of dm_sysobject like
checkin(), checkout(), save(), etc. that would be used to retrieve the number,
increment the number, and save the object.
(A more elaborate kind of sequencing described above is the subject of a sample
business object service, called "AutoName", that accompanies DFC 5.1 but is too
complex to present in this manual.)
2. Service-based business object (SBO), the subject of the Simple_SBO example, will
provide a simpler interface to obtaining the correct centralized number and saving it
to the TBO. It provides methods for getting the value stored and saving the next
number back into the Docbase. These methods can hide the details of locking and
unlocking the TBO objects, fetching and saving the other attributes of the TBO
objects, and so on.
° The most important method of this service is the getUniqueNumber() method that
fetches and increments the number according to the number type (PO, INV, etc.).
The other methods of this service are mainly for management purposes.
° Other methods will include 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 will be designed generically enough to
provide number formatting patterns and other filters.

Documentum Confidential and Proprietary Page 3-3


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

Figure 3-1 - AutoNumber Schema


DfTypedObject

«interface»
IDfBusinessObject
DfPersistentObject +getVersion()
+getVersionString()
+isCompatible()
+supportsFeature()
DfService
«interface»
IAutoName
+getVersion()
+getNextNumber() DfSysObject «interface»
+getVendorString()
+isCompatible() IAutoNameType
+checkin() +getUniqueNumber()
+save() +setNumber()

AutoNameType «datatype»
AutoName Docbase Type:
-type_name
-type_name com_accelera_autonumber
-current_number
-current_number
-max_number
-max_number
+getUniqueNumber()
+getNextNumber()
+setNumber()
+checkin()
«uses»
+save()
#checkRange()
#validate()
-setNextNumber()

A Simple Type-based Object Example

Introduction
As described in the "Solution: Documentum Business Objects" section, this Simple_TBO
program will be an application that fetches the Docbase object containing the existing
number, increments it, and saves the newly incremented value back to the Docbase. In
order to accomplish this, the following must be implemented:
• Assume that this example will work with a variety of separate, distinct numbering
sequences.
• A new Docbase type must be created, called "com_accelera_autonumber", that is a
subtype of the Docbase "dm_sysobject" type. This new type defines the schema for
the different numbering schemes, called numbering types in this example.
• Each com_accelera_autonumber object will store in its "current_number"
field/attribute the last value returned from the getUniqueNumber() method. This
"current_number" value will be used to calculate the next number in the sequence
defined for that numbering type. The object will also store any other fields that
require persistence for this example.
r_object_id name type_name current_number max_number
090000000101a8b7 Purchase Order PO 590124 99999999999
090000000101a8cb Invoice INV 30822 99999999999

Documentum Confidential and Proprietary Page 3-4


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

090000000101af58 Patent Application DCMPAT 944 9999999


090000000101b032 Contract Document DCMCON 730822 99999999

• A new Java class, called AutoNumberType, implements the business rules by


providing methods for incrementing the number as well as overriding operations, like
checkin() and save() to guarantee that the number is always within the bounds set
in the number type.
• This AutoNumberType class inherits from (extends) DfSysObject and will also
provide the implementation for all the DfSysObject methods it needs to override and
extend (like checkin(), save() and checkout()), as well as implementing new
implementation specific methods, like getUniqueNumber(), checkRange(), etc.).
• An interface for AutoNumberType, called, IAutoNumberType, will provide the means
to publicly use the object. This interface could extend IDfSysObject (although, for
clarity purposes Documentum recommends against this, so you should just override
only the necessary methods of the interface). (See page 7-4 for checklist for
subclassing dm_document).
• The AutoNumberType class will also be able to create an original
com_accelera_autonumber Docbase object if it doesn't already exist using its static
addNewAutoNumberType() method. The addNewAutoNumberType() method uses
the standard IDfSession.newObject() factory method to create a new instance of
the com_accelera_autonumber type.
• The Simple_TBO class will be a stand-alone Java application that tests the
AutoNumberType by obtaining and outputting the current number, causing the
number to increment and storing it back into the Docbase.
• A Simple_TBO test application is stateless from the TBOs 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, instead of numbers relative to each
computer or Simple_TBO instance.
• Simple_TBO calls the static addNewAutoNumberType() method to create a new
instance of the com_accelera_autonumber type if it can't find the specified type.
The files to create will be:
• Simple_TBO.java
• AutoNumberType.java
• IAutoNumberType.java
Plus, the AutoNumberType class must be registered in the dbor.properties file.

Documentum Confidential and Proprietary Page 3-5


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

Implementing the AutoNumberType TBO


This section will step you through the creation of the AutoNumberType business object a
type-based business object (TBO). The "A Simple Service-based Object Example"
section will step you through a service-based business object (SBO) to access this object.
1. Create the new IAutoNameType interface.
1.1. Define a new interface, called IAutoNameType that extends the
IDfBusinessObject interface. The IDfBusinessObject interface defines four
abstract methods for which its implementing concrete classes must provide.
Remember, it is acceptable for the implementing class to inherit the overridden
method implementations from its superclasses,
1.2. In the interface, prototype all the public methods that are new to the Docbase
object extended class as well as any public or protected overriding methods that
you wish publicly expose.
/* 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;
}

2. Extend DfSysObject with the new AutoNumberType class


The AutoNumberType TBO class definition wraps a Docbase object of type
"com_accelera_autonumber" and exposes getters and setters for the object's attributes
as well as checkin() and save() method overrides. The AutoNumberType class inherits
all the methods and properties of DfSysObject, IAutoNumberType, and
IDfBusinessObject (inherently through IAutoNumberType), so there is no reason to
rewrite or override inherited methods that will not alter the behavior of the existing type,
so if the IAutoNumberType interface needs to allow users of the object to call the
checkin() method on the interface, but is not providing any new behavior, all that is
needed is to declare the checkin() method in the interface and let the class inherit the
method from DfSysObject.
The AutoNumberType class extends the DFC DfSysObject class by changing the
behavior of two of its methods (save(), and checkinEx()) and by adding six new
private, protected and public methods related to auto-sequence numbering and its
management (getUniqueNumber(), setNextNumber(), setNumber(), checkRange(),
validate(), and addNewAutoNumberType()).

2.1. Create a new class, AutoNumberType, and extend the desired DFC class that
provides the closest behaviors and features to your needs. For example,
extending DfSysObject allows your objects to inherit nearly 500 public methods

Documentum Confidential and Proprietary Page 3-6


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

from its superclasses. Be sure to implement the TBO IAutoNumberType


interface also.
/* AutoNumberType.java
*/
package com.accelera.autonumber;

import com.documentum.fc.client.*;
import com.documentum.fc.common.*;

public class AutoNumberType extends DfSysObject implements IAutoNumberType


{
}

3. Implement the methods of IDfBusinessObject


3.1. In the AutoNumberType class, add the String constants that will be used for the
getVersion() and getVendorString() methods.
public static final String strCOPYRIGHT =
"Copyright (c) Documentum, Inc., 2002";
public static final String strVERSION = "1.0";

3.2. Since the AutoNumberType class implements the IDfBusinessObect class, and
the IDfBusinessObject interface defines four abstract methods, your new class
must implement overrides for each of the four methods, getVersion(),
getVendorString(), isCompatible(), and supportsFeature(), as follows:

Documentum Confidential and Proprietary Page 3-7


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

/* 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");
}

public boolean supportsFeature( String s )


{
String strFeatures = "uniquenumber, subclassing";

if( strFeatures.indexOf( s )== -1 )


return false;

return true; }
}

4. Override DfSysObject methods


4.1. Inside the AutoNumberType class, override any methods that require adherence to
the business rules for the com_accelera_autonumber type. These are two
methods, save() and checkinEx() as show below. Each method should call the
validate() method before forwarding the call to its superclass implementation.

The save() and checkinEx() methods were chosen because they are the points
at which the validation of the business rules need to be applied. The service, and
any other user of the Docbase object will modify it using checkout() / save() or
checkout() / checkin() combinations. Intuitively, you might have chosen the
checkin() method instead of the checkinEx() method. However, in this case,
all the DfSysObject.checkin() method does is call the checkinEx() method. So
we have chosen to implement the checkinEx() method instead.

Documentum Confidential and Proprietary Page 3-8


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

(Note: Sometimes you call the superclass implementation first, and other times you call
it after your extending code. There will even be times where the superclass
implementation should not be called at all.)
public void save() throws DfException
{
validate();
super.save();
}

The checkin() method is final so you cannot override it. This is because the checkin()
method just calls checkinEx() polymorphically. There is no reason to validate the
object twice. The checkinEx() method performs a check in with additional application-
specific attributes.
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 forward their calls to other methods. When overriding
methods, be sure to consider whether the method forwards its call to another method to
avoid performing the same override twice. With this in mind, DFC has declared some of
these methods as final to help you avoid overriding the method unnecessarily. This
includes methods like IDfSysObject.checkin() and checkout(), getContent(), and
several others.

5. Numbering Scheme methods


Now that you have finished overriding the methods of the superclasses, you can
implement the six methods of the new AutoNumberType class related to the numbering
scheme.
5.1. In the AutoNumberType class, implement the getUniqueNumber(),
setNextNumber(), and setNumber() methods. The getUniqueNumber() simply
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 is used to set the initial value of the
"current_number" field. By default, Simple_TBO will set it to "1". Implement
the methods as follows:

Documentum Confidential and Proprietary Page 3-9


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

Due to the fact that the three methods on lines 22, 23, and 24, listed below need to
perform a checkout(), modify attributes, and save() as an atomic operation,
they need to be part of a managed transaction. Since nesting session transactions
is not supported, the setNumber() method throws an exception if either the caller
has not supplied a managed transaction. The code on lines 13-18 performs this
test. In other words, you need to make the user supply a transaction for this
operation to function correctly. If the setNumber() fetches the next number, but
it is not saved back into the Docbase, the next person calling getUniqueNumber()
will get the same number. This is against the specified business rules.

Documentum Confidential and Proprietary Page 3-10


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

1 public String getUniqueNumber( IDfSessionManager sMgr )


2 throws DfException
3 {
4 return setNextNumber( sMgr );
5 }
6
7
8 private String setNextNumber( IDfSessionManager sMgr )
9 throws DfException
10 {
11 String strRetVal = null;
12
13 if( ! sMgr.isTransactionActive() )
14 {
15 DfException e = new DfException();
16 e.setMessage( "no transaction available" );
17 throw e;
18 }
19
20 try
21 {
22 checkout(); // lock
23 strRetVal = setNumber( null );
24 save(); // unlock and update
25
26 }
27 catch( DfException e )
28 {
29
30 sMgr.setTransactionRollbackOnly();
31
32 e.setMessage( strRetVal + e.getMessage());
33
34 throw e;
35 }
36
37 return strRetVal;
38 }//end setNextNumber()
39
40
41 public String setNumber( String strNewNumber ) throws DfException
42 {
43 if( strNewNumber != null )
44 {
45 setString( "current_number", strNewNumber );
46 }
47 else
48 {
49 strNewNumber = getString( "current_number" );
50
51 long n = Long.parseLong( strNewNumber );
52 checkRange( n+1 );
53 strNewNumber = String.valueOf( ++n );
54
55 setString( "current_number", strNewNumber );
56 }
57
58 return strNewNumber;
59 }
60

5.2. There are two methods related to the implementation of the business rules for this
type of object, validate() and checkRange(). The checkRange() method
checks a numeric value for validity before attempting to save it into the Docbase

Documentum Confidential and Proprietary Page 3-11


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

object. The validate() method fetches the "current_number" from the object
and forwards it to the checkRange() method for validation. Either of these
methods will 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()

6. Add a new Number sequencing Type - AutoNumberType instance


The last method to implement is the addNewAutoNumberType() method. This method is
static so that it can be used as a utility to add new objects of this type. If it weren't
static, it would require that an object of this type be instantiated before being able to
create one, thus start a vicious cycle. The AutoNumberType is tied to a version of a
Docbase object with its own r_object_id. If there isn't an object to fetch, then you can't
call getObject() to instantiate an AutoNumberType. If you can't get an instance of
AutoNumberType, then you can't call getUniqueNumber(). Therefore, call the
addNewAutoNumberType() method whenever a new numbering sequence is needed. It
will set the starting number and set the maximum range to the specified value. Another
side effect of being static is that it is hidden from the public interface and would need to
be used by maintenance programs only, or internal methods of the class can call it
transparently.

Documentum Confidential and Proprietary Page 3-12


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

public static void addNewAutoNumberType(


IDfSessionManager sMgr,
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()

7. 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.
7.1. Use Documentum Developer Studio to develop a portable DocApp:

Documentum Confidential and Proprietary Page 3-13


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

Figure 3-2 - Installing a new Docbase Type

7.2. 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

7.3. 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();

8. 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:

Documentum Confidential and Proprietary Page 3-14


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

com_accelera_autonumber=type,com.accelera.autonumber.AutoNumberType,1.0

This registers the new business object with Documentum 5.1so that any time any
Docbase objects from this new table are fetched, the Docbase object is used to populate
the AutoNumberType object.
(see Caution regarding manually editing the DBOR on page 3-2.)
You should write a program the uses the new IDfDbor and IDfDborEntry interfaces to
register the new AutoNumberType business object.

Documentum Confidential and Proprietary Page 3-15


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

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;
}
}//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.

Documentum Confidential and Proprietary Page 3-16


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

Editing the 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.
9. Deploy and Set up the new Business Object
Once the program successfully compiles, it needs to exist in the CLASSPATH or
installed into the Java Extension Library.
Optionally, you can pass a CLASSPATH as a command-line argument as follows:
java -cp "%classpath%" Simple_TBO DocbaseName "PO" username password [domain]

Implementing the Simple_TBO Test program


This test program is designed to mimic a regular caller / consumer of a TBO object.
1. Create the new Simple_TBO class
2. 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 String m_strDocbaseName;


private String m_strUserName;
private String m_strPassword;
private String 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
Simple_TBO class to prevent writing all the methods and variables as static,
establishing a session manager identity, and calling the test routine.
3.1. In the begin() method, construct a new session manager object using the
newSessionManager() method of IDfClient. Then register a user's credentials
as an identity in the session manager, using the
IDfSessionManager.setIdentity() method.

Documentum Confidential and Proprietary Page 3-17


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

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);
}
}

4. Parse the command line arguments into private variables

Documentum Confidential and Proprietary Page 3-18


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

private boolean parseCmdLine( String[] args )


{
try
{
m_strDocbaseName = args[0]; // check DocbaseName
m_strAutoNumberType = args[1];
m_strUserName = args[2]; // check AutoNameType
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_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;
}

5. Test the new object type.


5.1. 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".
5.2. Then call the getUniqueNumber() method.
5.3. Display the number you retrieved.
5.4. Set the next number back into the Docbase and release any locks you may have
established on the object.
5.5. Save the object with the overridden save() method.

Documentum Confidential and Proprietary Page 3-19


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

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 doesn't exist, tell the class to add one for you.


if( number == null )
{
AutoNumberType.addNewAutoNumberType( sMgr,
strDocbaseName,
strAutoNumberTable,
strAutoNumberType,
strAutoNumberType,
"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;
}
}

Documentum Confidential and Proprietary Page 3-20


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

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

A Simple Service-based Object Example

Introduction
As described in the "Solution: Documentum Business Objects" section, this Simple_SBO
program will be an application that fetches the next sequence number according to the
specified number type in a given Docbase and increments it. In order to accomplish this,
the following issues must be implemented:
• Assume that this example will work with a variety of separate, distinct numbering
sequence types ("PO", "INV", etc.).
• A new DBOF service interface will be created, called IAutoNumber, which is
implemented by the AutoNumber class, and provides the public access to the
numbering service for the given types.
• A Simple_SBO test application will be created to call the service and fetch the next
number in sequence of the given type if an instance of that type exists in the Docbase.
Trying it from different computers will still obtain the correct number in sequence.

Implementing the AutoNumber Service Based Object (SBO)


This section will step you through the creation of the AutoNumber service. It will use the
values stored in the AutoNumberType created in the previous section.
1. Create the new IAutoName service interface
1.1. Define a new interface, called IAutoNumber, which extends the IDfService
interface. The IDfService interface defines three abstract methods the must be
implemented in the AutoNumber class.

Documentum Confidential and Proprietary Page 3-21


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

1.2. In the IAutoNumber interface, prototype the minimal number of methods that
abstract the details of the service. In this case, you will prototype the
getNextNumber() method only.
/* 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;
}

2. Extend DfService with the new AutoNumber class


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.
2.1. Create a new class, AutoNumber, and extend DfService class and implement its
IAutoNumber interface.
public class AutoNumber extends DfService implements IAutoNumber
{
}

2.2. In the AutoNumber class, add the String constants that will be used for the
getVersion() and getVendorString() methods.
public static final String strCOPYRIGHT =
"Copyright (c) Documentum, Inc., 2002";
public static final String strVERSION = "1.0";

2.3. Since the AutoNumber class extends the DfService class, and the DfService
class defines three abstract methods, your new class must implement overrides
for each of those methods, getVersion(), getVendorString(),
isCompatibile() as follows:

Documentum Confidential and Proprietary Page 3-22


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

/* 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., 2002";
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

3. Numbering Scheme methods


Now that you have finished overriding the methods of its superclass, you can implement
the public interface for the service. In this case the service only has one method, the
getNextNumber() method.

3.1. In the AutoNumber class, implement the getNextNumber() method. The


getNextNumber() method needs to be as stateless as possible, so pass the
Docbase name to it each time it is called. A second argument is the numbering
type (e.g. "PO", "INV", etc.). The method will need to perform a Docbase query
to obtain the matching AutoNumberType object, if it exists, return the currently
stored number, and store next number back into the Docbase.
3.2. Each time the getNextNumber() service method is called, it assumes that the
caller has established a session manager and uses that session manager to obtain
a session for Docbase access.
3.3. The getNextNumber() service method fetches an AutoNumberType Docbase
object, using the session.getObjectByQualification() method, and updates
it.
3.4. Since it is mandatory that releaseSession() is called when its matching
getSession() method is used, releaseSession() is put in a finally block as
shown below in order to guarantee it executes.

Documentum Confidential and Proprietary Page 3-23


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

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() );

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;
}

4. Map the new IAutoNumber service interface to the AutoNumber service class.
Better known as "registering the service with the DBOR", you need to map the interface
to the class so that the newService() method will know how to construct an AutoNumber
object as opposed to any others. This registration can be done manually, or you can write
a program to perform the installation of the service.

Documentum Confidential and Proprietary Page 3-24


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

4.1. To register by hand, in the "DFC_DATA\config" directory (usually


"c:\Documentum\config"), add the following entry anywhere in the
dbor.properties file:
com.accelera.autonumber.IAutoNumber=service,com.accelera.autonumber.AutoNumber,1.0

4.2. More appropriately, you should allow IDfDbor do this work since it will not
allow duplicate entries. Writing a method that calls the
mapDocbaseTypeToClassName() method on page 3-16. The beginInstall()
method below is designed to register either TBO or SBO entries. If it is called
with bService set to true, then the strNewDocbaseType parameter represents the
service interface (e.g. com.accelera.autonumber.IAutoNumber).
private boolean beginInstall( IDfSessionManager sMgr,
boolean bService,
String strDocbaseName,
String strNewDocbaseType,
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;
}

5. Deploy the Service.

Documentum Confidential and Proprietary Page 3-25


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

5.1. Once the program successfully compiles, it needs to exist in the CLASSPATH or
installed into the Java Extension Library. Optionally, you can pass a CLASSPATH
as a command-line argument as follows:
java -cp ".;%classpath% " Simple_SBO accelera "INV" username password, domain

Implementing the Simple_SBO Test program


The test program is designed to mimic a regular caller / consumer of the SBO service.
1. Create the new Simple_SBO class.
2. Declare the private instance variables.
// Simple_SBO.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_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";

}// end: class Simple_SBO

3. Write the main() methods and instantiate the class. This involves parsing the
command line arguments into variables, instantiating the Simple_SBO class to prevent
writing all the methods and variables as static, establishing a session manager
identity, and calling the test routine.
3.1. 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.

Documentum Confidential and Proprietary Page 3-26


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

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();
}
}

3.2. Parse the command line and save the values into the private variables.

Documentum Confidential and Proprietary Page 3-27


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

private boolean parseCmdLine( String[] args )


{
try
{
m_strDocbaseName = args[0]; // check DocbaseName
m_strAutoNumberType = args[1];
m_strUserName = args[2]; // check AutoNameType
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;
}

3.3. Write the test() method that accesses the type-based object, gets the next
number from the TBO, and instructs it to increment itself as follows.
3.3.A. Note the use of the getSession() method that obtains a session from the
session manager. This method is supplied by the DfService class and will
return the session created by the session manager.

Documentum Confidential and Proprietary Page 3-28


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

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 );
}
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()

Run 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 will prove that
the service is producing sequential numbers by type:

Documentum Confidential and Proprietary Page 3-29


Developing Your First Business Objects Documentum Business Objects Framework (DBOF)

Figure 3-4 - Sample running test SBO program

Documentum Confidential and Proprietary Page 3-30


Documentum Business Object Registry (DBOR) Documentum Business Objects Framework (DBOF)

Chapter 4 Documentum Business


Object Registry (DBOR)
Overview
The Documentum Business Object Registry (DBOR) serves as a catalog of available
business objects installed on the computer. It provides mapping of Java interfaces to
their respective Java classes (for service based BOs) and binding Docbase object types to
their respective Java classes (for type based BOs). The Java classes implement the
business logic. The mappings/bindings defined in the DBOR are configurable, allowing
the developer to change the implementation (i.e. binding to another class) without
changing the client application that uses the business logic.
Currently, the DBOR is available for the Java runtime environment. When a given
business object is used at runtime, the DBOF factory mechanism instantiates the
registered business object class using information stored in the DBOR. The Java DBOR
interface provides lookup functions and methods for adding and removing registry entries
(items).

Architecture of the DBOR


Currently, the DBOR is implemented as a Java properties file that is located in a directory
relative to the environment variable DFC_DATA (usually C:\Documentum). When DFC
is installed, DFC_DATA is automatically registered on the server or computer to which
DFC is installed. The default location for a Windows based server is
DFC_DATA\config. The DBOR properties file is named dbor.properties.
Additionally, it is possible to define a Java system property "dfc.data" to override the
DFC_DATA definition. The following example shows how to pass the "dfc.data"
system property to the Java Virtual Machine (JVM):
java.exe –Ddfc.data="c:\Documentum" YourProgram

Caution: The current implementation of the Documentum Business Objects Registry


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 as well as
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. You should not attempt to edit this file without using the DborManage
DBOR maintenance tool,

Properties File Syntax


The DBOR should be viewed and modified with a DFC utility that uses the IDfDbor
interface to access the registry information. You can write your own, or use the

Documentum Confidential and Proprietary Page 4-1


Documentum Business Object Registry (DBOR) Documentum Business Objects Framework (DBOF)

DborManage utility included in dfc.jar. In absence of this tool, the DBOR properties file
can be viewed and modified using a standard text editor such as Windows notepad.exe or
vi on Unix. It follows the standard Java properties file syntax. Each line is a
configuration item, and comment lines start with '#'. It is allowed to have empty lines
between configuration items.
You can modify the DBOR programmatically using the IDfDbor interface. The IDfDbor
interface will guarantee that no duplicate entries exist.
A DBOR item uses the following configuration syntax:
Item
(Interface or Docbase Type) Type Java class Version
IProduct service com.documentum.services.Product 1.0
com.documentum.services. type com.documentum.services.
IProductType ProductType

For example, use the DborManage tool to register the IProduct service:
java DborManage register com.documentum.services.IProduct service
com.documentum.services.Product 1.0

Where the DBOR entry fields correspond to similar IDfDborEntry setters and getters:
DBOR IDfDborEntry
Field Method Description
name setName() The item being bound or mapped to a Java class.
getName()
The item is a service name (SBO), a Docbase type
name (TBO) for example, "my_sop", or the name
of an interface mapped to the same Docbase type
as another class. For service based business
objects (SBOs) use the fully qualified Java class
name of the service interface. (example:
IAutoName.class.getName() returns
com.documentum.services.AutoName)
type setServiceBased() Specifies either "type" or "service". The keyword
getServiceBased()
for TBO is "type", for SBO it is "service"
java setJavaClass() The fully qualified Java class name that
class getJavaClass()
implements the TBO or SBO. The Java class must
be located within the current CLASSPATH of the
JVM. Note: Java does not allow mixing classes
from different class loaders. For example, a
DBOR call will fail if the dfc.jar file is referenced
in the system CLASSPATH environment (e.g.
using standard DFC as installed with the DFC
installer) but the Java class that implements the
SBO or TBO is located in a WAR file. Therefore,

Documentum Confidential and Proprietary Page 4-2


Documentum Business Object Registry (DBOR) Documentum Business Objects Framework (DBOF)

if you decide to deploy using a WAR file,


everything required for DBOF must be included
with the WAR file.
version setVersion() The version of the Java implementation. This is
getVersion()
typically in the form "1.0". The version is
currently not evaluated and is defined mainly for
documentation purposes and for future extensions
of DBOR.

The following is sample output from the DborManage utility showing examples of valid
DBOR items:
TYPE Docbase type : com_accelera_autonumber
mapped to class : com.accelera.autonumber.AutoNumberType
Version : 1.0

SERVICE interface : com.accelera.autonumber.IAutoNumber


mapped to class : com.accelera.autonumber.AutoNumber
Version : 1.0

Caution: Documentum does not support the remapping of any standard "dm_" .Docbase
types.

DBOR Deployment
A valid copy of the DBOR properties file must be deployed to every computer where
TBOs and SBOs are used in a DFC-based application. For example, if a TBO or SBO is
used in Desktop Client customizations, the DBOR file must be deployed to all those
computers running the customizations. For WDK, ASP, and JSP environments, the
DBOR needs to be deployed on the application server computers. The DBOR properties
file must be located in the file system in a directory defined with DFC_DATA.
The Business Object developer is responsible for the following:
• Report an error if DFC 5.1 or above is not installed. The DBOF framework does not
work on DFC 4.2 or earlier systems.
• Copy the JAR or WAR file (archive) of the Business Objects to the file system.
Either copy the archive into the JRE/lib/ext directory of the JVM, or modify the
CLASSPATH so that the applications can find the Java classes in the archive.
• Handle Business Object version issues. Potential version conflicts can occur when
the JAR file of an existing BO is merely replaced with a new one.
• The DBOR registry must be updated to map the Business Object Java classes to their
associated interfaces or Docbase types.
• For TBOs, the new Docbase type must be added. The actual Docbase records of the
new Docbase type are usually added later.

Documentum Confidential and Proprietary Page 4-3


Documentum Business Object Registry (DBOR) Documentum Business Objects Framework (DBOF)

• Constructing and deploying a COM interface. The classes and the methods of the
business objects are available to COM through the IDispatch interface. This is only
required if the business object adds new methods to a TBO. You could also create an
IDL file and/or a TypeLib file (.TLB) but that approach involves more manual work
for the programmer.

DBOR Usage - Runtime Object Lookup


When a DBOF factory class instantiates a business object at runtime, it automatically
looks up the Java class from the DBOR. Service BOs are instantiated using the
IDfClient.newService() service factory method. If a DBOR item is not present for
the given SBO, an exception is thrown.
Type based BO instances are added using the IDfSession.newObject() type based
factory method in DFC. To instantiate the TBO at runtime use the getObject() like
methods. Unlike with SBOs, if a specified TBO entry does not exist, the factory method
does not fail. Instead, the default DFC mechanism is automatically used, which
constructs in instance of the most derived subclass known to DFC associated with the
supertype of the custom TBO Docbase type. For example, if a TBO of type
"dm_autonumber" is instantiated and no DBOR entry is present, the object factory would
construct a DfSysObject instead of an AutoNumberType.
For performance reasons the DBOR is cached in memory but it is reloaded whenever the
registry is modified. That way, the registry can be modified while an application is
running. When this happens, the next call to DBOR will use the updated configuration.
Existing instances of the modified SBO or TBO are not impacted.

DBOR Management
The IDfDbor Java interface not only provides lookup functions but also provides
methods to add and remove items from the DBOR properties file. This functionality is
intended for tools that need to automatically modify the DBOR such as installers or
convenience tools for the developer.
A reference to the DBOR can be obtained through the IDfClient.getDbor() method.
There are five methods available from DBOF that can be used by DBOR configuration or
management tools:
Dbor Method Description
register() Registers a new "service" or "type" in the DBOR. This method
maps the service interface or the Docbase type to a Java class. Pass
a configured IDfDborEntry object to this method. An entry can
only be registered if it does not already exist. Otherwise, an
exception is thrown.
unregister() Removes the matching entry from the DBOR registry file.
lookupService() Given the entry name (left of the equals), returns the fully qualified
class name of the Java class of the service.

Documentum Confidential and Proprietary Page 4-4


Documentum Business Object Registry (DBOR) Documentum Business Objects Framework (DBOF)

lookupObject() Given the entry name (left of the equals), returns the fully qualified
class name of the Java class for this TBO.
getAll() Gets a list of all entries (service based and type based) in the
registry.

The following Java sample code shows how to configure the DBOR entry if it does not
already exist:

Documentum Confidential and Proprietary Page 4-5


Documentum Business Object Registry (DBOR) Documentum Business Objects Framework (DBOF)

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 it's a "type"
}
catch( DfServiceNotFoundException e )
{ // service not found
}

// You should get here...the service should not exist if you're 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 it's 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 );
entry.setServiceBased( bDborService );
entry.setJavaClass( strJavaClass );
entry.setVersion( strVersion );

Documentum Confidential and Proprietary Page 4-6


Documentum Business Object Registry (DBOR) Documentum Business Objects Framework (DBOF)

dbor.register( entry );
System.out.println( "Successful:" );
dbor = null; // unlock the 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()

Error Handling
Applications access the DBOR indirectly for lookup or directly for registration or
removal of services. There are several scenarios where one or more operations may fail
for a number of reasons. There are cases where standard exceptions are thrown and there
are some cases where Java runtime exceptions are thrown. The Java exception
mechanism is used to indicate problems with DBOR access.
The following error handling is implemented for DBOR access:
• DBOR properties file not present in expected location: Check the DFC_DATA
environment variable or the "dfc.data" system property.
• DBOR properties file is there but the item is not configured: For TBOs that are
retrieved using getObject()-like methods, the default behavior will ignore this
condition when the DBOR can't be found. This may cause some problems when
accessing the TBO later. This should not be a problem if only standard DFC
classes such as IDfPersistentObject, IDfFolder are used. For SBOs that or
obtained using the IDfClient.newService() factory method, an exception will
be thrown because there is no fallback mechanism. The exception thrown is of
type DfDborNotFoundException and the application should catch this exception
to handle this scenario. The factory method only indicates that newService()
will throw a DfServiceException, which is a supertype of the real exception,
DfServiceInstantiationException. If the exception message refers to a

Documentum Confidential and Proprietary Page 4-7


Documentum Business Object Registry (DBOR) Documentum Business Objects Framework (DBOF)

"class not found" condition, the item might not be registered correctly or the
classpath is not correct.
• DBOR item not configured properly: For both TBOs and SBOs, if the DBOR
properties file contains an item that does not follow the specified syntax, an
exception of type DfServiceCriticalException is thrown. This is an
unchecked Java runtime exception (RuntimeException). This can occur due to
manual entry or corrupt contents to the registry. This will manifest itself when
registering a service with the same name as an entry that already exists as a type.
It will also occur when the lookupService() method finds a matching entry but
it is a "type" instead. Likewise, this will occur when the lookupObject()
method finds a matching entry but it is a "service" instead.
• Problems with DBOR registration: Always 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 DBOR unregister(): Throws either a
DfServiceCriticalException or a DfServiceException. The
DfServiceException indicates there was 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 show up in the "throws" clause of the method signature.

Documentum Confidential and Proprietary Page 4-8


DBOF Session Manager Documentum Business Objects Framework (DBOF)

Chapter 5 DBOF Session Manager


Introduction
One of the key differences between working with previous releases of DFC and DFC 5 is
that DBOF supports stateless interactions between an application and one or more
Docbase servers. The ability for an application to have stateless connections with
Docbases and application servers is essential for web environments, which are naturally
stateless. The DBOF Docbase Session Manager enables and controls this capability.
Programmers who develop Documentum Business Objects (DBO) and those who use
DBOs in their applications use methods and hooks provided by the Session Manager.
Whenever an application needs to authenticate against or access an eContent Server, it
calls the DFC 5.1 Session Manager to obtain a "managed session" or to invoke Docbase
transactions. When working with managed sessions, the developer separates user
identities, Docbases, and DFC sessions. For example, when calling a service, you first
register identity/Docbase pairs with session manager and then call the service method,
passing the Docbase name. The session manager then transparently connects new
sessions as needed and releases them when it determines the session is no longer needed
(think of this as a managed session expiration).
The IDfSessionManager interface provides six functional groups of methods and its
own set of exception classes.
• Managed session handling, including creating a new session, releasing the session.
and reacquiring a session from the pool.
• Transaction processing, which provides the ability to commit or abort a series of
actions to a Docbase.
• Authentication, which allows the program to register a list of IDfLoginInfo /
Docbase pairs (list of "Identities") with the session manager so the session manager
can transparently reconnect to that Docbase if needed. In addition, a new
authentication mechanism is supported, called a "Principal Identity", which allows the
session manager to use a special trusted user identity to act as a proxy for connecting
to different Docbases without a password.
• Client session pool locking, for when a stateless service needs to return one or more
stateful persistent objects that might need to be accessed after the session times out
and is recycled to the DMCL session pool. DBOF provides methods for the DFC
client to control locking of the session to the session DMCL pool until the client
decides to relinquish control of the lock.
• Session Manager statistics, provides session manager state information relating to
the list of Docbases to which it has in its identity list along with a session iterator.
• Error handling, catching both checked and unchecked exception objects thrown by
business object processing.

Documentum Confidential and Proprietary Page 5-1


DBOF Session Manager Documentum Business Objects Framework (DBOF)

Session Manager Features and Details


This section describes the Session Manager and how it can be used by client applications.

DMCL Session Pool


The session manager automatically provides DMCL session pooling transparently. The
client application does not need to specify any special parameters to select session
management mode (or managed session mode). The session manager reads the DMCL
client session pool settings and automatically switches to the corresponding mode.
Session pooling becomes active when the DMCL.INI variable
connect_pooling_enabled is set. Without this setting, session pooling is disabled and
even session manager sessions will remain open until the service session is released and
the session object is garbage collected, even if the session was obtained using
sMgr.newSession(). If session pooling is disabled the session will only be closed when
the service session is garbage collected. Therefore, enabling the DMCL session pooling
switch is highly recommended.
Here is a sample dmcl.ini file that has session pooling switched enabled:
[DMAPI_CONFIGURATION]
cache_queries = T
connect_pooling_enabled = T
max_session_count = 1000

Please refer to the DFC manual for all the options for configuring the client.
Essentially, when session pooling is enabled, disconnecting from and releasing the
session does not actually disconnect the session. The pooling mechanism leaves the
session active to be used later.
With managed sessions, the session manager does not immediately put released sessions
back into the session pool. Instead, released sessions remain available for reuse for a
small amount of time.

DFC Session Control and Lifecycle


The lifetime of the session manager object (not the session, but the manager) is under
control of the client application, that is, the session manager object used by a service
must be explicitly constructed or destructed. Once identities are defined, the session
manager manages the DFC sessions transparently such that the client typically never
handles a DFC session directly. Direct DFC session access by the client application is
not recommended. The methods of a service will request a DFC session handle from the
session manager when they require Docbase access and will release the DFC session
quickly, usually upon returning from the service method. The session manager
implementation keeps track of the requested sessions and only gives them back to pool
when the reference counter is back to zero. The release of a session will only occur if
session pooling is enabled.

Documentum Confidential and Proprietary Page 5-2


DBOF Session Manager Documentum Business Objects Framework (DBOF)

Session Timeout
The session manager does not provide methods to adjust the timeout handling for the
client application. A DFC session will not timeout and recycle to the session pool as long
as its session manager object lives and the DFC session is not released by a server
method. However, it is still possible for a server side session to expire without the client
application being aware. The session manager transparently always guarantees that a
given session is available for its clients. Therefore, the client could hold on to a session
manager object forever if it needed to and at any time it would always be able to
reconnect managed sessions that had been released.
During idle time, the session manager will release session manager sessions and save
them in the session pool to be reused by other session managers that may require a
Docbase connection.
Once the session manager is no longer needed, it can be discarded without any special
action. For example, if the session manager is stored in an HTTP session object, there is
no need for additional cleanup work once the session object has expired. However, there
are a number of issues that you must take into account. In order for the session manager
to be discarded there must not be pending sessions. The following scenarios must be
avoided as they are programming errors:
• sMgr.beginClientControl() with no matching end method

• sMgr.beginTransaction() with no matching commitTransaction() or


abortTransaction() methods

• A DFC session is not released inside a service


When a session manager is garbage collected (Java garbage collector), a test is performed
to check for pending sessions. If sessions are pending, a message is written to the log
file. Therefore, service developers are encouraged to check the log file when testing an
application based on DBOF.
Managed session timeouts can cause, and hide, transaction logic errors. The hidden logic
errors can really make programming difficult unless you can find these errors. For
example:
1 private void serviceMethod1( String strDocbaseName, IDfId idDoc )
2 {
3 session = sMgr.getSession( strDocbaseName );
4 IDfPersistenObject doc = session.getObject( idDoc );
5 sMgr.release();
6 serviceMethod2( strDocbaseName, doc );
7 }

8 private void serviceMethod2( String strDocbaseName,


9 IDfPersistentObject doc )
10 {
11 session = doc.getSession(); // WRONG! should get a session first
12 String name = doc.getObjectName();
13 }

Documentum Confidential and Proprietary Page 5-3


DBOF Session Manager Documentum Business Objects Framework (DBOF)

At first glance, it would seem that since the persistent object, doc, has a getSession()
method to retrieve the session through which the object was fetched, would fetch a valid
session. In this case, the retrieved session might be stale. Even f the session were not
released, the session could still be stale due to a timeout.
Prior to session manager, this would never have been expected to work since it was never
appropriate to touch an object after its session was released. Since DFC 5.1 recommends
releasing sessions frequently back to the session pool, this kind of logic could be
inappropriately performed within a service call if the service developer does not
completely understand this issue. The key point is that sometimes line 12 works and
sometimes it does not. It works if the session manager has not yet timed out the session
that was released on line 5. Setting the DebugSessionManager system property will
invalidate the session immediately upon release. In which case, line 12 would always
fail, thereby uncovering the faulty logic.
To assist with debugging managed session timeout issues, define the
DebugSessionManager Java Virtual Machine system property when you start your
program or add the property to you Java debugger environment.
java -D DebugSessionManager -classpath %classpath% YourProgram

When this system property is defined, the session manager times out the sessions and
recycles them as often as possible to assist you in locating logic errors.

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 will use
the appropriate IDfLoginInfo object when connecting to a given Docbase.
The following example shows calling the same service for different Docbases:
IDfClient client = DfClient.getLocalClient();
IDfSessionManager sMgr = client.newSessionManager();
sMgr.setIdentity( strDocbase1, loginInfo );
sMgr.setIdentity( strDocbase2, loginInfo );

IMyService anyService = (IMyService)


client.newService( IMyService.class.getName(), sMgr );

anyService.call(strDocbase1);
anyService.call(strDocbase2);

When the "Principal identity" mechanism is used, the principal name must be the same
name on all Docbases. Furthermore, principal support must be enabled. The following
example shows calling services in different Docbases using a principal:

Documentum Confidential and Proprietary Page 5-4


DBOF Session Manager Documentum Business Objects Framework (DBOF)

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);

Note now the Principal Name was only set once but two different Docbases are accessed.

Managed Sessions

Service Implementation
This section presents Session Manager related considerations for the implementation of
service based business objects. Please refer to Chapter 6: "Service Based Business
Objects" 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 Chapter 6: Service Based 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 Java's 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.

Documentum Confidential and Proprietary Page 5-5


DBOF Session Manager Documentum Business Objects Framework (DBOF)

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 (e.g. 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 DBOF transaction.
Caution should be exercised when using transaction processing withing a business object
service.
• 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().

Documentum Confidential and Proprietary Page 5-6


DBOF Session Manager Documentum Business Objects Framework (DBOF)

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();
}
}

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, let’s say there
are two services: one service creates a few folders and then the second service stores

Documentum Confidential and Proprietary Page 5-7


DBOF Session Manager Documentum Business Objects Framework (DBOF)

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.
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:

Documentum Confidential and Proprietary Page 5-8


DBOF Session Manager Documentum Business Objects Framework (DBOF)

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 ) ;
If either of these service
sMgr.beginTransaction(); methods throws and exception,
try
{ commit is bypassed and abort
s1.doDocbaseUpdate(); is executed.
s2.doDocbaseUpdate();
sMgr.commitTransaction(); Each of the
}
catch (Exception e) doDocbaseUpdate() methods
{ call sMgr.getSession().
sMgr.abortTransaction();
}

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.
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

Documentum Confidential and Proprietary Page 5-9


DBOF Session Manager Documentum Business Objects Framework (DBOF)

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 (e.g. 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.
Calls to beginClientControl() can also be nested as long as there is a matching
endClientControl() for each beginClientControl().

Documentum Confidential and Proprietary Page 5-10


DBOF Session Manager Documentum Business Objects Framework (DBOF)

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 DBOF 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 DBOF 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.getStatistics()method 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 (e.g. 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:

Documentum Confidential and Proprietary Page 5-11


DBOF Session Manager Documentum Business Objects Framework (DBOF)

• 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.

Authentication
The Session Manager supports two different ways for it to connect to sessions on your
behalf. The first is relatively straightforward. You register a Docbase name you would
like the session manager to connect you to in the future. Along with the Docbase name,
you supply a typical IDfLoginInfo object that specifies the user name and password the
session manager should use to connect you to that specified Docbase. This Docbase /
IDfLoginInfo pair is called a "Manual Identity", or "Identity" for short. The other
connection mechanism uses what is called a "Principal Identity" (similar in concept as
J2EE Principal Identities).
You register a typical IDfLoginInfo object with the session manager along with the
Docbase you would like the session manager to connect you to when needed.
The Session Manager allows the program to register a list of IDfLoginInfo/Docbase
pairs (list of "Identities") with the session manager so the session manager can
transparently reconnect to that Docbase whenever necessary.
In addition, another new authentication mechanism is supported, called a "Principal
Identity", which allows the session manager to use a special trusted user identity to act
as a proxy for connecting to different Docbases without the user supplying a password to
each service or session manager.

Setting and Managing Identities


When the session manager connects to Docbase servers, it must do so as a particular user.
To the session manager, these are called "Identities". For this to occur properly, you
must first register that Docbase user login information with the session manager.

Documentum Confidential and Proprietary Page 5-12


DBOF Session Manager Documentum Business Objects Framework (DBOF)

Identities can be authenticated on demand by the client application or left up to the


service implementation to validate the user login parameters. In this case, the validation
takes place when the service implementation first requests a DFC session.
Once identities are defined, the only session related parameter passed to a service method
is the Docbase name. The session manager then automatically ensures that the DFC
sessions are handled properly by retrieving the IDfLoginInfo list entry matching the
specified Docbase name. An identity must be defined in the Session Manager for each
Docbase the service will access.
Managing Manual Identities
Setting an Identity
To set a manual identity, IDfLoginInfo parameters must be provided by the user or from
a configuration mechanism. The identity can then be associated with a specific Docbase
name.
Figure 5-1 - Session Manager "Identities"
Session Manager List of
IDfLoginInfo / Docbase Identity pairs
IDfLoginInfo Docbase
User Passwd Domn Session Manager
Dave
Dave pwd3
pwd3 dmn
dmn Docbase
Docbase33
Dave pwd1
Dave pwd1 dmn
dmn Docbase
Docbase11 session released
session active

Docbase 1 Docbase 2 Docbase 3

Dave pwd John pwd Dave pwd


Mary pwd Mary pwd John pwd

First, a data object which implements the standard DFC interface IDfLoginInfo must be
constructed which is composed of the following properties (with the corresponding getter
and setter methods):
• User: user name
• Password: password for user
• Domain (optional): NT domain name
Example:
IDfLoginInfo loginInfo = clientx.getLoginInfo();
loginInfo.setUser( user );
loginInfo.setPassword( password );

if( domain != null )


loginInfo.setDomain( domain );

Documentum Confidential and Proprietary Page 5-13


DBOF Session Manager Documentum Business Objects Framework (DBOF)

This is the standard mechanism used since DFC version 1.0. The only difference is that
the IDfClient.newSession() method is not called.
When a new identity is registered to a session manager object, the login parameters, as
described above, must be specified together along with the Docbase name. The Session
Manager allows multiple identities to be defined using the setIdentity() method, up to
one for each Docbase. The Session Manager maintains a lookup table, keyed on Docbase
name.
Example:
IDfClient client = DfClient.getLocalClient();
IDfSessionManager sMgr = client.newSessionManager();
sMgr.setIdentity( strDocbase, loginInfo );

Once identities are defined, the service implementation only needs to establish a session
along with the corresponding Docbase name. The session manager automatically obtains
the identity that matches the given Docbase and creates a session with that Docbase.
Where possible, instead of creating a new session, a session pool session is reused.
NOTE: A consecutive call to the setIdentity() method using the same Docbase will
produce a DfServiceException. If such a call is required, be sure to call the
clearIdentity() method first.

Authenticate Identity
Identities can be authenticated on demand by using the
sessionManager.authenticate() method.
In some cases, you may want to have immediate user authentication, for example, in a
login dialog. In this case, the method sessionManager.authenticate() method can be
called after the identities are defined. The session manager then immediately tries to
connect to the Docbase and throws an exception (DfAuthenticationException) if
either the user or password is invalid. The authenticate()method does nothing more
than request a session. The session is cached to lessen the performance issues when
calling a service shortly after authenticating a user.
Example:
IDfClient client = DfClient.getLocalClient();
IDfSessionManager sMgr = client.newSessionManager();
sMgr.setIdentity( strDocbase, loginInfo );
sMgr.authenticate( strDocbase );

NOTE: When using the Session Manager in a web application, make sure there is a
separate Session Manager instance for each user session. If you use the same Session
Manager, different users will share the same Docbase permissions, which may
compromise security.

Documentum Confidential and Proprietary Page 5-14


DBOF Session Manager Documentum Business Objects Framework (DBOF)

Remove Identity
Identities can be removed from a session manager by using the
sessionManager.clearIdentity() method together with the Docbase name. Remove
all the identities using the sessionManager.clearIdentities() method.
To release the session to a specific Docbase, the clearIdentity() method must be
called. To disconnect from all Docbases, call the sessionManager.clearIdentities()
method. Any Docbase requests made after clearing the identity for that Docbase causes a
DfIdentityException. Design applications in a way that would not attempt access to
Docbases without valid identities.

Check Identity
To check for a specific user identity registered in the Session Manager for given
Docbase, use the sMgr.hasIdentity() method. Optionally, a collection of all the
identities for a specified Docbase can be retrieved using the sMgr.getIdentities()
method. In addition, you can obtain a list of Docbases to which the Session Manager has
identities using the IDfSessionManagerStatitics.getDocbases() method. Obtain a
reference to an IDfSessionManagerStatistics object using the
sessionManager.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 );
}

Documentum Confidential and Proprietary Page 5-15


DBOF Session Manager Documentum Business Objects Framework (DBOF)

Enabling Principal Identity Authentication


A Principal Identity is a single Docbase account name that the session manager can use to
establish server sessions with those Docbases as needed. The general idea is to register
with the session manager a user name that is a common user account name on all the
Docbases required by the service.
When using the principal identity mechanism, a trusted identity must be defined in all the
Docbases the service will connect to. This identity is able to generate a special login
ticket on behalf of the principal. The special login ticket is a temporary password valid
for the super user to use for client impersonation for a short period. Since the principal
name does not include a password (since it was authenticated by the framework) the
trusted identity is used to generate a login ticket for the principal. A login ticket is a
String that generally looks like, "DM_TICKET = 1536802154710167". Read, "Server
Fundamentals", Chapter 2 for more information on login tickets.
In addition, you must write a new class that implements the one method of the
IDfPrincipalSupport interface, the IDfPrincipalSupport.getSession() method.
This getSession() method takes two arguments, a Docbase name string and a Principal
name string and returns an IDfSession reference. It is your responsibility to establish a
new session from the Docbase, and ensure that the mechanism protects the user account
information of the super user. When principal support is set, when a client calls
getSession(), the overridden getSession() method of the custom subclass of
IDfPrincipalSupport is called polymorphically. The following example shows an
excerpt from a getSession() method implemented in a subclass of
DfPrincipalSupport. The principal support getSession() method is called when: (A)
principal support is set, and (B) whenever a managed session is requested.

Figure 5-2 - IDfPrincipalSupport.getSession() method implementation


1 IDfSession sessionUser;
2
3 String strTicket = sessionSuper.apiGet( "getlogin",
4 strPrincipalName );
5
6 IDfLoginInfo loginUser = new DfLoginInfo();
7 loginUser.setUser( strPrincipalName );
8 loginUser.setPassword( strTicket );
9
10 IDfSession sessionUser = client.getSession( strDocbaseName,
11 loginUser );
12 return sessionUser; // good for only about 5 minutes. (depending on the
13 // server settings over which you have no control)
14 }

Principal support is not switched on by default. To enable Principal support, you must
call the setPrincipalSupport() method.
client.setPrincipalSupport( new YourPrincipalSupport(loginSuper) );
When calling the client.setPrincipalSupport() method, supply a reference to an
active IDfLoginInfo user of a super user or system administrator. The Principal Support
object can save this login object in its memory.

Documentum Confidential and Proprietary Page 5-16


DBOF Session Manager Documentum Business Objects Framework (DBOF)

Example:

IDfLoginInfo loginInfo = new DfLoginInfo();


loginInfo.setUser(superUser);
loginInfo.setPassword(superUsersPasswd);
DfSessionManager sMgr = new DfSessionManager();
client.setPrincipalSupport(new SamplePrincipalSupport(loginInfo));

Principal support is used to generate the DFC session for the principal being
authenticated. The principal service support interface IDfPrincipalSupport defines a
method getSession() which returns the DFC session for a given Docbase/principal
combination. It is up to the implementation how to obtain the trusted identity. A sample
class is available that demonstrates an implementation of a class that implements the
IDfPrincipalSupport interface, called SamplePrincipalSupport. The constructor
takes login information of a super user that is able to generate login tickets for users. The
limitation of this implementation is that the super user must have the same login
credentials for all Docbases it serves.
The login credentials for the super user need to be passed or read by the service to get
started. Great care must be taken so as not to expose any security risks to your
corporation.

Figure 5-3 - Principal Identity Diagram


support.getsession( "Docbase1", "Dave" );
support.getsession( "Docbase3", "Dave" );
Session Manager List of
Session Pool Principal Identities
Principal_Name Pwd Docbase
session saSession 1. Dave fake
session apiGet("getlog in", Dave fake Docbase1
Docbase1
"Dave"); Dave
Dave fake
fake Docbase3
Docbase3
saSession3
saSession2
saSession1

file.properties.encrypt
sysAdmin,
sysAdmin,saPwd
saPwd
Docbase 1 Docbase 2 Docbase 3

Dave pwd John pwd Dave pwd


sysAdmin sysAdmin sysAdmin

Setting a Principal Identity


The setPrincipalName() method sets the principal name. For ease of use, the principal
name is passed as a string and not as a Principal object. Once a principal is registered, it

Documentum Confidential and Proprietary Page 5-17


DBOF Session Manager Documentum Business Objects Framework (DBOF)

is used for all Docbases being accessed. It is not possible to define a principal for a
specific Docbase.
Example:

IDfClient client = DfClient.getLocalClient();


IDfSessionManager sMgr = client.newSessionManager();
sMgr.setPrincipalName( strPrincipalName );

NOTE: Principal support is only used when no manual identity is available. In other
words when both principal and manual identities are set, the manual identity has priority
and is used for user authentication.

Check for Principal Identity


The principal name currently used for a session can be retrieved using the
getPrincipalName() method which will return null if no principal is defined.

Reset Principal Identity


Use the setPrincipalName() method, passing "null" instead of a principal name, to
reset a principal name. A consecutive call of the setPrincipalName() method will
replace the previous setting of the principal.

Documentum Confidential and Proprietary Page 5-18


Service Based Business Objects Documentum Business Objects Framework (DBOF)

Chapter 6 Service Based Business


Objects
Introduction
Service based Business Objects (SBO) are functional components that are not bound or
related to a specific Docbase object type. They are components that may operate on
multiple object types, retrieve different objects types unrelated to Documentum objects
(e.g. external email message), and typically perform some processing.
An example of a service-based object is a Documentum IInbox object that retrieves items
from a user inbox and performs several operations, such as removing and forwarding
items. Such a business object is not tied to a specific Docbase object type, therefore it
may operate on different types of objects.
For readers familiar with Enterprise Java Beans (EJB), a Service based Business Object is
similar in concept to a Session Bean whereas a Type based Business Object is more
similar to an Entity Bean.

Architecture

Design Time
A Service based Business Objects is created by extending the
com.documentum.fc.client.DfService class and implementing its corresponding
IDfService interface. The DfService class is an abstract class that implements some of
the common methods for most services.
The service interface and service abstract class (IDfService, and DfService) define the
following methods:
• The getName() method returns a logical service name. The default implementation
in DfService returns the fully qualified interface name that is implemented by the
service class. (such as com.documentum.services.inbox.IInbox )
• The getVersion() method returns the current version of the service as a string. The
version is a string and must match the following pattern:
<major version>.<minor version>. For example, "1.0". In the DfService
class, this is an abstract method and must be overridden by all services.
• The getVendorString() method returns copyright statement. If a service were
provided by Documentum, the vendor string would be
"Copyright (c) Documentum, Inc. 2002. All Rights reserved."
• The isCompatible() method can be used to check if the implementation of a service
is compatible with a specific service version. This allows a service client to use
different versions of a service and the client can then determine if the service is
compatible with specific functionality. Versioning is possible only for the

Documentum Confidential and Proprietary Page 6-1


Service Based Business Objects Documentum Business Objects Framework (DBOF)

implementation of a service but not for the interface. Java does not support multiple
versions of the interface.
• The supportsFeature() method is used to define a feature catalog for every service
which can then be queried by the client. Based on this information, specific UI
features can then be switched on or off. The default implementation in DfService
returns false.
• The getSessionManager() method allows a service to access the service’s session
manager handle.
• The getSession() method returns a DFC session object. Each time one of these
methods is called, a corresponding releaseSession() method is required. The
default implementation in DfSession calls the session manager to return the DFC
session for the given Docbase name.
• The releaseSession() method is used to return a session established with
getSession(). In this case, DfSession just invokes the session manager.

• The cleanupResources() method provides the caller of a service an opportunity to


release some service specific resources before the Java garbage collector will collect
the object. The default implementation does not do anything.
Runtime
A Service based Business Object client application uses the following factory method for
service instantiation:
public IDfService newService( String name, IDfSessionManager sMgr )
throws DfServiceException;

This method is implemented by the DFC interface IDfClient in


com.documentum.fc.client. The factory takes the service name (see naming
conventions) and a session manager as parameters, and returns the service interface,
which must be downcast to the specific service interface. The service name is used to
lookup the Java implementation in the DBOR registry file. The session manager is stored
as a member of the service and the service implementation accesses the session manager
when a DFC session is required.
The newSessionManager() method in IDfClient constructs an IDfSessionManager
(see session manager section) object, which is used as a session handle for all services.
The session manager must be constructed before the service is created.

Rules and Guidelines (with examples)

Implementing Service based Business Objects


Naming Conventions
DBOF framework does not impose special constraints for service naming. However,
names must be unique within a DBOR so it is recommended that you use the fully
qualified service interface name as the service name. This ensures no naming conflicts

Documentum Confidential and Proprietary Page 6-2


Service Based Business Objects Documentum Business Objects Framework (DBOF)

outside of the namespace of the service, and is more convenient for calling the factory
methods.
Example: The following example shows how you can simply pass the class name to the
factory method when using the interface name as the service name
IAutoName autoname = (IAutoName)client.newService(
IAutoName.class.getName(), sMgr);

Service Parameters
Wherever possible, avoid using Java system classes as method parameters or return
values. If a DBOF service interface were exposed to a non-Java environment like
Microsoft COM, these classes would make the porting even more difficult. The DFC
common package provides a few Java interfaces and classes that could be used in
replacements for some Java system classes:
• Remember that the new DJCB COM Bridge supports IDispatch interface for COM
programs.
• IDfList / DfList in a place of java.util.Vector.

• IDfProperties / DfProperties in a place of java.util.Hashtable

• IDfTime / DfTime in a place of java.util.Date


Stateful vs. Stateless Approach
The stateless approach is preferred and is applicable when a service interface can be
exposed as a stateless interface without losing interface clarity and performance. This
practice simplifies exposing a service interface in the remote mode. In addition, the
stateless interface works better in a multithreading environment. For example, a check-in
service would need optional parameters, like keep lock, version label, etc.
Example: The following interface uses the stateful pattern, which should be avoided:

interface ICheckin extends DfService


{
public void setRetainLock( boolean retainLock );
public void setVersionLabels( String newVersionLabels );

. . .

public void checkin( IDfSysObject object ) throws DfServiceException;

. . .
}

Example: The following example uses the stateless approach in which case all
parameters are passed to the method at once. This approach can be confusing especially
if there are many optional method parameters to specify. However, this approach may be
useful if the number of optional method parameters is small.

Documentum Confidential and Proprietary Page 6-3


Service Based Business Objects Documentum Business Objects Framework (DBOF)

interface ICheckin extends DfService


{
public void checkin( IDfSysObject object, boolean retainLock,
String newVersionLabels, . . .)
throws DfServiceException;

. . .
}

Example: The following example also uses the stateless approach but passes the method
parameters using a data object. This is a cleaner approach than above when dealing with
many parameters. Therefore, this is the preferred approach as long as overhead is not an
issue:
Example:

interface ICheckin extends DfService


{
public IDfCheckinConfig newConfig ();

public void checkin( IDfSysObject object, ICheckinConfig config )


throws DfServiceException;

. . .
}

An ICheckinConfig object holds all parameters required for check-in. A data holder
object contains getters and setters for all parameters.

Overriding DfService Abstract Methods is Required


Service based Business Objects extend the DfService class. They implement the
abstract methods that DfService defines, which include the following:
• getVersion()

• getVendorString()

• isCompatible()

Docbase Name is Required


The Docbase name must be passed either to the service or to every method. The Docbase
name is needed in order acquire a DFC session. This allows multiple Docbase access.
The advantage of passing the Docbase name to every method is that the methods become
truly stateless, allowing the Docbase to be switched between server method calls. If
multiple Docbases are not required, and statelessness is not an issue, the service can
declare a String member and a setter method, which defines the Docbase name.
Example:

Documentum Confidential and Proprietary Page 6-4


Service Based Business Objects Documentum Business Objects Framework (DBOF)

private String m_strDocbase = null;

public void setDocbase( String strDocbase )


{
m_strDocbase = strDocbase;
}

In most cases, it is not possible to anticipate the environments in which a service is going
to be used and therefore it is recommended that the Docbase name be passed to every
method call.
Caching persistent data in the service implementation
Caching dynamic persistent data in the service implementation is not recommended. It is
better to rely on the client cache. Otherwise, the Java based cache may be out of synch
with the client cache when either a client application aborts a transaction or another
service modifies the object.
Extended Service Methods
The service methods must be defined to implement the different service functions. This
can be one or more independent (i.e. stateless) methods. Each method must get a session
and release it when finished. It is important to release the session even in case of an error
in order to make it available.
The following example shows how to structure a service method:

public void doSomething( String strDocbase, String strParam1 )


{
IDfSession session = getSession( strDocbase );
try
{
// do something with strParam1 using session to access Docbase
}
catch( Exception e )
{
// handle error
}
finally
{
releaseSession( session );
}
}

Calling a Service based Business Object


Instantiating a Service based Business Object
The client application should instantiate a new Service based Business Object each time
one is needed rather than retaining one that already exits. This approach is both thread-
safe and efficient since it requires little resource overhead. For example, in a web
application that calls a specific service during an HTTP request, the service is

Documentum Confidential and Proprietary Page 6-5


Service Based Business Objects Documentum Business Objects Framework (DBOF)

instantiated, executed and then discarded when the request is done. The required steps to
instantiate a service are:
1. Define the user login information with an IDfLoginInfo object.
2. Instantiate a session manager object.
3. Call the service factory method:
Example:
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 );
IAutoName autoname = (IAutoName)
client.newService( IAutoName.class.getName(), sMgr);

Error Handling
The session factory method may throw an exception indicating one of the following
problems:
• DfDborNotFoundException: This exception is thrown in case the DBOR does not
exist.
• DfServiceNotFoundException: The DBOR was found but the service is not
configured.
• DfServiceInstantiationException: In this case, the Java class configured in
DBOR cannot be instantiated. This may happen if the Java class was not found in the
CLASSPATH or is an invalid data class. Java classes on application servers sometime
have security protection that may also cause this exception to be thrown.

Documentum Confidential and Proprietary Page 6-6


Type Based Business Objects Documentum Business Objects Framework (DBOF)

Chapter 7 Type Based Business


Objects
Introduction
Type Based Objects (TBO) are extensions of basic DFC types such as
IDfPersitentObject, IDfSysObject, IDfDocument, IDfFolder, or any other class
that inherently extends IDfPersistentObject. They allow a developer to encapsulate
some business logic that is specific to a particular object type. There are two main
reasons for creating TBO:
• Providing a new behavior for existing or new object types. For instance, a
developer may decide to add new get and set methods for object specific
attributes or add new methods like addProduct() to a Catalog TBO.
• Customizing low level operations to enforce data validations, referential integrity
and object specific business rules. For instance, a developer may decide to
override the save() and checkin() methods to be able to validate data before
saving them in the persistent storage.
This chapter contains the following main sections:
• "Architecture" on page 7-1.
• "Implementation Rules, Guidelines, and Examples" on page 7-3.
• "Calling Rules, Guidelines, and Examples" on page 7-7.

Architecture
They key point of Type-based Business Objects is to allow a programmer to implement
new business rules for new Docbase types. In order to succeed in this, all other programs
that access the Docbase objects of this new type must be forced to use the overridden
methods supplied by the business object. In Documentum 5.1, whenever a program calls
newObject() or getObject() like methods, the Documentum 5.1 system will perform
the following tests:
• The system determines the actual Docbase object type and fetches that object along
with its supertype parts.
• Checks the dbor.properties registry file (DBOR) to determine if there is a mapping
between the custom type and a Java class.
o If so, that Java class is instantiated and getObject() returns that object.
You will not need to downcast to the subtype to use any of the overridden
methods, like getObjectId(), getString(), save(), etc.

Documentum Confidential and Proprietary Page 7-1


Type Based Business Objects Documentum Business Objects Framework (DBOF)

You will need to downcast to the interface of the new subtype in order to
call any new methods (or methods of subclasses of
IDfPersistentObject)
o If the object type is not mapped in the DBOR to a Java class, the standard
DFC class is instantiated (e.g. DfDocument).
(Caution: Because this mapping will not occur with ANY "UPDATE" queries,
modifying the attributes of type based objects by way of "UPDATE" queries is
discouraged.)
The following three code samples would retrieve the same "com_accelera_autonumber"
Docbase object AND execute the code in the overridden checkout() method (of
AutoNumberType) because of the DBOR mapping and polymorphism.
String strDQL =
"dm_document where r_object_id = '091a64c18001b382'";

IDfDocument number = (IDfDocument)


session.getObjectByQualification( strDQL );
number.checkout();

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'";

IAutoNumberType number = (IAutoNumberType)


session.getObjectByQualification( strDQL );
number.checkout();

Object Factory
A client application uses the same standard DFC factory method to construct a new TBO
as any other Docbase type. Use session.newObject() to create a new TBO object.
ICatalog catalog = (ICatalog)session.newObject( "catalog" );

Use any of the getObject() series of methods to create an instance of the new class
(TBO) designed to implement the new Docbase type.
ICatalog catalog = (ICatalog)session.getObject( idDoc );

The session.newObject() method constructs a new type based business object (TBO)
that is mapped to a specific Docbase type. Usually, there is a one-to-one relationship
between the Docbase type and the business object type (e.g. "catalog" is mapped to

Documentum Confidential and Proprietary Page 7-2


Type Based Business Objects Documentum Business Objects Framework (DBOF)

ICatalog). Therefore, the factory method checks the DBOR to determine which Java
class is mapped to a given Docbase object type.
Figure 7-1 - Sample DBOR Entry
catalog type com.documentum.catalog.Catalog 1.0

In this case, the Docbase object type "catalog" is configured in the dbor.properties file
and the object type is mapped to the com.documentum.catalog.Catalog Java class
which implements the ICatalog interface. This interface exposes the specific catalog
functions and the client application can use this interface to handle and control a catalog
object.
For a given Docbase object type, there may be multiple entries registered in the DBOR.
This may be the case when there are different applications that handle the same object
type slightly differently. For this reason there are additional factory methods that can be
used to explicitly specify the interface used to handle the given object. These methods
are defined as follows:
catalog type com.documentum.catalog.Catalog 1.0
ICatalog2 type com.documentum.catalog.Catalog2 1.0

ICatalog2 catalog = (ICatalog2)getObjectWithInterface( idDoc,


ICatalog2.class.getName() );

String strDql = "dm_document where r_object_id = '" + idDoc.getId() + "'";


ICatalog2 catalog = (ICatalog2)getObjectByQualificationWithInterface(
strDql, ICatalog2.class.getName() );

These methods will lookup the interface name in the DBOR and instantiate the registered
implementation used to handle the object instance. If the interface is not registered, an
exception will be thrown. In addition, when using this method, the interface name is not
the Docbase name but the key to lookup the implementation in DBOR. The Docbase
type name is used to implement the default behavior of a type based object. For special
handling the interface name is used.

Implementation Rules, Guidelines, and Examples


There are four categories of methods to consider when designing a TBO
1. New methods that do not exist in DFC today. (Extended methods that add new
functionality.)
2. New getter and setter methods to expose custom attributes (for convenience reasons).
3. Attribute validation regardless of the state of other attributes. In this case, you would
override setString(), appendString(), setRepeatingString() and add
validation code for each attribute we have to validate.
4. Attribute validation in the context of other attributes. For example, if we validate
minRange we must make sure it is less than maxRange. This type of validation can

Documentum Confidential and Proprietary Page 7-3


Type Based Business Objects Documentum Business Objects Framework (DBOF)

only be accomplished when the object is persisted. This requires overriding the
save(), checkinEx(), etc. methods.

Use the following points as a checklist when developing with type based business objects
(TBOs).
• When designing a TBO, the interface of the type based object must inherit from
IDfBusinessObject. The IDfBusinessObject interface defines four abstract
methods that must be implemented by its implementing classes: getVersion(),
getVendorString(), isCompatible(), supportsFeature().
public interface IAutoNumberType extends IDfBusinessObject
{
}

• You should then "abstract" the interface to the new Docbase type by defining a
collection of methods that you recommend programmers use to access objects of this
new type.
While it seems natural to define the interface to also extend the interface of its
corresponding Docbase supertype interface, a best practice recommendation is to
completely define all the methods of the interface. For example, if checkin() and
checkout() are methods that will be called by programmers on the object directly,
they should be defined in the interface instead of merely extending IDfDocument.
This prevents "polluting" of the new interface and makes it less confusing to other
programmers as to which methods there are to choose from.
interface IAutoNumberType extends IDfBusinessObject, IDfDocument

• When defining the Java class that will be mapped to the new Docbase type, you must
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
{
}

• At the same time, the TBO class must implement the four methods of the
IDfBusinessObject class as follows:

IDfBusinessObject
methods Description
getVersion() Define a constant String in the class that describes the version (e.g.
"1.0", "2.1", etc.) of the Java class for this object type. This
method should return that constant version String.
getVendorString() Define a constant String in the class that describes the copyright
information (e.g. "Copyright (C), 2002, Documentum, Inc., All
Rights Reserved". This method should return that constant String.

Documentum Confidential and Proprietary Page 7-4


Type Based Business Objects Documentum Business Objects Framework (DBOF)

isCompatible() The parameter specifies a version to check whether this version of


this TBO is compatible with or not. Returns true or false.
supportsFeature() This method should determine if the specified feature is supported
by this business object. The parameter is a String that specifies
the BO feature in question. Tis parameter should not be a versions
string. You could define it as a code that could be looked up.
This method returns true or false depending on whether the
feature is supported or not.

• Always keep in mind that eventually your new TBO class might be subclassed by a
future TBO. If you need to prevent subclassing, consider defining the class as "final".
(You should exercise caution when defining a class as final as doing so could prevent
anyone from developing a work-around method if the method does not perform
exactly as needed.)
• In overridden methods, be sure to call the method of the superclass if its behavior is
still required for overridden methods. Sometimes, your extra code should be added
before the superclass method, other times, the superclass method should be called
first, and sometimes, the superclass method should not be called at all.
public void save()
{
validate(); // new extra functionality
super.save(); // inherited functionality
}

• Some inherited superclass methods call other methods for their implementation. For
example, DfSysObject.checkout(), calls DfSysObject.checkoutEx(null,
null, null). If you override both checkout() and checkoutEx() in your
subclass, provide the extra functionality in both methods, and then call the inherited
superclass methods in both cases, the extra functionality will be provided twice,
which could be undesirable. For this reason, some methods, like checkin(),
checkout(), getContent(), and several others, have been changed to final,
meaning, they can't be overridden in a subclass.

Documentum Confidential and Proprietary Page 7-5


Type Based Business Objects Documentum Business Objects Framework (DBOF)

public void checkout() // NOT ALLOWED BECAUSE IT IS FINAL


{
preDownloadTest(); // This would get performed again during checkoutEx()
super.checkout(); // inherited functionality calls checkoutEx()
}

public IDfId checkoutEx( String versionLabel,


String compoundArchValue,
String specialAppValue ) throws DfException
{
preDownloadTest(); // new extra functionality
// inherited functionality
return super.checkoutEx( versionLabel, compoundArchValue,
specualAppValue );
}

• For new methods, try to write them so that they can be implemented as stateless as
possible. This can be quite involved but the following guidelines should be used:
Type based business objects are always tied to a DFC session object during the entire
life of a Java object instance. During the life of such a type based business object, the
session manager must be locked to make sure the session is not recycled back to the
pool.
o 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 );
}
finally
{
sMgr.endClientControl();
}
}

o Use the session manager for Docbase sessions whenever possible.


o Use the IDfTypedObject.setSessionManager() method when
serializing a TBO or when returning a TBO from a service method. The
following example shows how to properly return a TBO from within an
SBO method.
o Client Control and setSessionManager() are alternative approaches to
doing basically the same thing.

Documentum Confidential and Proprietary Page 7-6


Type Based Business Objects Documentum Business Objects Framework (DBOF)

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():


• All the attributes of the object are copied into a DFC cache on the Java side
• The persistent object will be "severed" from its original DFC session
• A reference to the specified session manager object will be stored in the persistent
object
The setSessionManager() method allows a program to get and set any attributes while
their values will be retrieved and stored on the Java side. When the program executes a
method that requires communication with the Docbase (e.g. save(), checkin(),
checkout(), etc.), the internal implementation will automatically request a DFC session
from the session manager. The persistent object will then be fetched applying all changes
from the Java side to the DMCL cache, and in turn execute the requested action. Finally,
the DFC session object is released again. All this occurs transparently and the client
application does not notice this behavior.

Calling Rules, Guidelines, and Examples


Type based business objects are used either from within a service method or directly from
a client application. Use an IDfSession to instantiate a TBO object. Be sure to release
the session when finished with the object.
Within a method of an SBO, a session can be retrieved using the standard getSession()
method. Because the session is released when the service method is finished, the TBO
should not be stored in the service because the session object may become invalid.
Use the setSessionManager() method when:
• There is a reason to release the DFC session but keep an instance of the TBO.
• There is a reason to store the TBO in the SBO state.
When calling an SBO method that returns a TBO object, use the Client Control
mechanism before and after the call.

Documentum Confidential and Proprietary Page 7-7


Type Based Business Objects Documentum Business Objects Framework (DBOF)

Error Handling
The factory methods getObjectWithInterface() and
getObjectByQualificationWithInterface() may throw an exception indicating one
of the following problems:
Business Objects Exception class Description
DfDborNotFoundException Indicates that the dbor.properties file can't be
found in the DFC_DATA\config directory.
Check the DFC_DATA variable.
DfServiceNotFoundException Indicates the dbor.properties file was found but
the service was not found.
DfServiceInstantiationException The Java class was configured in the DBOR
but cannot be instantiated. The may occur if
the Java class was not found in the
CLASSPATH or is an invalid data class. Java
classes on application servers sometimes have
security protection that may also cause this
exception to be thrown.

Best Practices
Don't extend the DFC interface
For example, if your TBO class extends the DfDocument class, your interface for that
class could extend the IDfDocument interface. If you were to extend the interface, a user
of the interface would need to choose from over 500 methods. This "polluting" of the
interface seems unnecessary when designing a new type. The actual object still has those
methods available because the class extends DfDocument, so it does not prevent DFC
operations from internally utilizing those methods. Documentum recommends not
extending the interface and designing a new interface with only those methods that are
deemed necessary. The implementation can simply call super.method() inside the
methods of the class.

Remember to design your TBO to be subclassed


When you design a TBO, it is possible that others may wish to extend that object and add
additional features. For example, the simple AutoNumberType in chapter 3 simply
generates numbers in sequence. In a way, they are unique numbers. If someone wanted
to use the design and extend it with another kind of unique numbering system such as
UUID, stepped numbers, etc., AutoNumberType could end up becoming the base of a
whole new hierarchy.

Never create a TBO for a standard Docbase type


Remapping of standard Docbase types is discouraged and is not allowed. This could
possibly break many, if not all, applications that use those standard types and would

Documentum Confidential and Proprietary Page 7-8


Type Based Business Objects Documentum Business Objects Framework (DBOF)

make it extremely difficult to support. Therefore, Documentum prohibits remapping of


standard Docbase types to custom classes.

Documentum Confidential and Proprietary Page 7-9


Using Business Objects Documentum Business Objects Framework (DBOF)

Chapter 8 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.
For now, this chapter is missing the content until supplied by engineering.
The major sections of this chapter are:
• How to use a Business Object from WDK
• How to use a Business Object from Visual Basic using IDispatch
• Guidelines and Best Practices

How to use a Business Object from WDK


The biggest issues related to using DBOF services from WDK is the issues of session
management and user authentication. WDK session management functions are provided
by DFC via the IDfSessionManager interface. DBOF was designed to be used with
WDK.
WDK wraps nearly all the IDfSessionManager methods wrapped in the WDK
SessionManagerHttpBinding class and the IDocbaseAuth and IDocbaseAccess WDK
interfaces.
A managed IDfSession object is always associated with a WDK Component object.
From within any method of a WDK Component object, you can call any of its
getDfSession() methods listed in Table 8-1.

Table 8-1 - WDK Component getDfSession() methods


Component.getDfSession() Description
methods
getDfSession()
getDfSession(
REQUEST_LIFETIME )
getDfSession(
REQUEST_COMPONENT_LIFETIME )

The remainder of this section demonstrates the steps involved to call a DBOF service
from a WDK component. The sample service implements a simple phone book service
that provides a customer address lookup based on a given customer or phone number.
The following sample application involves:
• ICustomer service based business object.
• JSP / HTML form for user interface.
• A custom WDK form event handler to initiate the action.

Documentum Confidential and Proprietary Page 8-1


Using Business Objects Documentum Business Objects Framework (DBOF)

The user interface form appears as shown in Figure 8-1.


Figure 8-1 - 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;
}

These methods return the object ID of a customer object. Using that ID, you can retrieve
selected customer data attributes using the getCustomerData() method.
You can create a JSP page as shown in "Figure 8-1 - Customer Service user interface
WDK form". The form is implemented using a WDK form class named CustomerForm.
The button and text field labels are handled using the CustomerFormNls class. They are
configured using a properties file. The resources are referenced using Java constants that
are defined in the CutomserFormNls class. For example, the work "Phone" is mapped to
an ID_PHONE constant, which maps to the value of a number configured in a properties
file.
When the "Lookup" button is pressed, the CustomerForm.onLookupPhone() event
method is invoked. The JSP form layout is named, CustomerForm.jsp:

Documentum Confidential and Proprietary Page 8-2


Using Business Objects Documentum Business Objects Framework (DBOF)

<%@ 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"/>
</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>

When the "Lookup" button is pressed, the onLookupPhone() event method is invoked
and uses the ICustomer service to lookup the customer information based on the
provided number. The onLookupPhone() method uses the
SessionManagerHttpBinding WDK class to obtain a DFC session manager object prior
to instantiating the service. Once the service is constructed, the interface is downcasted
to the ICustomer type and then the two methods can be used.

Documentum Confidential and Proprietary Page 8-3


Using Business Objects Documentum Business Objects Framework (DBOF)

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]);
}
}

The implementation of the ICustomer methods will use the Docbase name and their
session manager objects to obtain and release a pooled session.
The onLookupPhone() method shown above performs the following functions:
• Obtains the phone number from the "PHONE" text box of the HTML form.
• The String[] data array is a detail related to the ICustomer.getCustomerData()
method. It happens to return an array of string references, one for each customer
attribute. (Hopefully, in the same order as the for fields are laid out. This
implementation detail that might be better served using a Hashtable object).
• To obtain a session manager reference, construct a new WDK
SessionManagerHttpBinding object. Then use its getSessionManager() method.
(Note: DfClient.getLocalClient() can be called as many times as needed during
an application without worrying about memory leakage since it is a singleton).
Once the session manager is obtained, call the client.newService() method to obtain
the ICustomer service object. The newService() method will use the DBOR to locate
the Java class associated with the interface and instantiate that object for you. The
newService() method requires two arguments, the service name, and a session manager
reference. Since the service name must be a fully qualified name of the service's
interface, use the ICustomer.class.getName() construct to obtain the fully qualified
interface name. You can only do this if the service interface can be imported during

Documentum Confidential and Proprietary Page 8-4


Using Business Objects Documentum Business Objects Framework (DBOF)

development time. Otherwise, you will have to use a string like,


"com.documentum.services.customerservice.ICustomer" instead.
Because you have downcasted the DfService object returned from the newService()
method to a specific ICustomer interface, you are able to call the two service methods.
Use the getCustomerIdFromPhone() method to ask the service to get the customer ID
from the Docbase for you. Using that ID, you can use the getCustomerData() method
to ask the service to get the rest of the customer's data attributes.
The last step in the example shows a loop that iterates through the string[] that was
returned from the getCustomerData() method to populate the HTML form fields with
the customer data values.

How to use a Business Object from Visual Basic using IDispatch


The key to using business objects from Visual Basic is use of the session manager. 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 DBOF 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 DBOF service
and call specific methods of that service. The main drawbacks of this approach are:
• Your Visual Basic will not provide a list of method names available from the service.
• The code will not be type-safe and can generate runtime errors that would not be
detectable during compilation.

Documentum Confidential and Proprietary Page 8-5


Using Business Objects Documentum Business Objects Framework (DBOF)

Dim clientx As DfClientX


Dim client As IDfClient
Dim loginInfo As IDfLoginInfo
Dim sMgr As IDfSessionManager
Dim session As IDfSession
Dim service As Object
Dim id As IDfId
Dim custData() As String
Dim attrList() As String
Dim ctlText As Text

Set clientx = New DFCLib.DfClientX ' or use CreateObject( "Documentum.Dfc" )


Set client = clientx.getLocalClient

Set sMgr = client.newSessionManager

Set service = client.newService("com.documentum.services.customer.ICustomer",_


sMgr )

attrList(0) = "phone"
attrList(1) = "name"
attrList(2) = "address"
attrList(3) = "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)

Guidelines and Best Practices

Fetching persistent objects

Documentum Confidential and Proprietary Page 8-6


Deploying Business Objects Documentum Business Objects Framework (DBOF)

Chapter 9 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.
DBOF 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 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 the DBOR on every computer that runs the
application. This entry must match the Java classes installed. The DBOR registry 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 the 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 DBOF, 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.

Documentum Confidential and Proprietary Page 9-1


Deploying Business Objects Documentum Business Objects Framework (DBOF)

Packaging example
Assume that we want to deploy the IAutoName sample service, which consists of a
several Java classes. These classes are shipped in a JAR file named "autoname.jar". The
JAR file is built as follows (assuming a Windows server and default installation
locations):
jar.exe -cvf autoname.jar com

com/
com/documentum/
com/documentum/services/
com/documentum/services/autoname/
com/documentum/services/autoname/AutoName.class
com/documentum/services/autoname/AutoNameScheme.class
com/documentum/services/autoname/IAutoName.class
com/documentum/services/autoname/IAutoNameScheme.class
com/documentum/services/autoname/INameGenerator.class
com/documentum/services/autoname/sample/
com/documentum/services/autoname/sample/RunAutoName.class
com/documentum/services/autoname/UniqueNameException.class

com/documentum/services/autoname/Installer.class

Business Object Registration


The 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:
com.documentum.services. service com.documentum.services.autoname. 1.0
autoname.IAutoName AutoName
dm_autoname type com.documentum.services.autoname. 1.0
AutoNameScheme

The DFC and the Business Objects Framework require the dfj.jar file. If it is not installed
with the DFC installer, the dfc.jar should be installed in the Documentum Shared files
directory, (e.g. c:\Program Files\Documentum\Shared).
To make the services available to the application, servlet, or application server, copy the
business object JAR file (e.g. the autoname.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

Documentum Confidential and Proprietary Page 9-2


Deploying Business Objects Documentum Business Objects Framework (DBOF)

• 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 can't
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.
• 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 (e.g. 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.autoname, 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:

Documentum Confidential and Proprietary Page 9-3


Deploying Business Objects Documentum Business Objects Framework (DBOF)

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.

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 the DBOR must be configured.

AutoName Components
If you want to install the AutoName sample business object, follow these steps:
• Copy the autoname.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.

Documentum Confidential and Proprietary Page 9-4

You might also like