Friday, August 8, 2008

How to test DTS Adlib

Goal
How to test the Adlib installation, or test a particular document.

Resolution
The steps to test the Adlib installation, or to test a particular document are outlined as follows:

1) Copy the attached files to C:\Temp on the DTS/RPTS server.

2) Open the WSA Sample Application from:
Start > All Programs > Adlib > Exponent Web Service Adaptor > Exponent WSAS Sample

3) Click the 'Submit Job Ticket' tab.

4) Click the Browse button next to the XML Job Ticket field.

5) For a DTS install, select C:\Temp\DTS_jobticket.xml.
For a DTS install, select C:\Temp\RPTS_jobticket.xml.

6) Click 'Validate' to ensure the file is valid (a success message is displayed in the window).

7) Click 'AddJob()' under the Validate button.

The status of the job will be printed in the "Web Service Response" window. Click the 'GetJobSatus()' button to view the progress. A pdf file should be created in C:\Temp if the job is successful.

Documentum Search Audit Trails

Q) How to collect audit trails of searches performed by users?
Documentum does not capture any audit events for searches performed. However, search statistics and reports can also be used to identify frequently used keywords and tune the search engine to provide accurate results.

The statistics can also be used for creating management reports if needed.

Design Approach:
1. Create a new persistent object (”sp_search_log”) to store Search log information
2. Customize the search component’s behaviour class’s onRenderEnd() method to create a new “sp_search_log” object
3. Save the object before displaying the JSP

Alternate Approaches:
1. Use JDBC to capture the information in a database table. Complicated approach involving opening database connections.
2. Create custom audit trails to create dm_audittrail objects. I have not yet studied the implications of this.

CREATING A NEW TYPE to store Search Logs:
CREATE TYPE "sp_search_log"
( “r_search_id” ID,
“userid” CHAR(10),
“userdisplayname” CHAR(200),
“deptcode” CHAR(6),
“keyword” CHAR(100) REPEATING,
“location” CHAR(250) REPEATING,
“attrib_namevalue” CHAR(250) REPEATING,
“starttimeofsearch” DATE,
“endtimeofsearch” DATE,
“noofresults” INT,
“noofvieweddocs” INT
) WITH SUPERTYPE NULL PUBLISH

OUTPUT OF DQL > new_object_ID 030004d2800001b9

ALTER TYPE “sp_search_log” DROP_FTINDEX ON “userid”
ALTER TYPE “sp_search_log” DROP_FTINDEX ON “userdisplayname”
ALTER TYPE “sp_search_log” DROP_FTINDEX ON “deptcode”
ALTER TYPE “sp_search_log” DROP_FTINDEX ON “location”
ALTER TYPE “sp_search_log” DROP_FTINDEX ON “attrib_namevalue”

Use this DQL to drop any fields if needed:
ALTER TYPE “sp_search_log” DROP “Field-Name” PUBLISH

Use this DQL to add new fields if needed later:
ALTER TYPE “sp_search_log” ADD “New-Field-Name” DATE PUBLISH
Note:
- “attrib_namevalue” CHAR(250) REPEATING will be used to store the params from advanced search in the form date=22/01/2006, etc.
- If the user uses a phrase search like “new york”, it can be stored in one keyword. If new york is used without quotes, it will be stored as two keywords

SAMPLE JAVA SOURCE CODE FRAGMENTS
Note: This code is meant to prove the concept. This may not be the best approach for performance.
A better approach could be to store the “starttimeofsearch” in an instance variable then, create & save the

sp_search_log object only once after the search operation is completed.

public class SearchEx extends com.documentum.dam.search.SearchEx
implements IControlListener, IDfQueryListener, Observer,
IReturnListener, IDragDropDataProvider, IDragSource, IDropTarget
{
private boolean m_loggedToDB = false;
private boolean m_loggedNoOfResultsToDB = false;
private boolean m_isFirstCall = true;public void onInit(ArgumentList args)
{
System.out.println(”## Inside custom search”);
String strQuery = args.get(”query”);
System.out.println(”## strQuery: ” + strQuery);
super.onInit(args);
}

public void onRenderEnd()
{
super.onRenderEnd();

if(m_loggedToDB == false && m_isFirstCall==true) {
createSearchLogObject();
m_isFirstCall = false;
}

if(m_loggedToDB == true && m_isFirstCall==false && m_loggedNoOfResultsToDB==false) {
updateSearchLogObject();
}
}

private void createSearchLogObject(){
String objectId = null;

IDfSession sess = this.getDfSession();

String userid = “Not found”;
try {
userid = sess.getLoginUserName();
System.out.println(”### userid: ” + userid);

String queryDesc = getQueryDescription();
System.out.println(”### queryDesc: ” + queryDesc);

IDfPersistentObject searchLog =
(IDfPersistentObject)sess.newObject(”sp_search_log”);
searchLog.setString(”userid”, userid);
searchLog.setString(”userdisplayname”, userid);
//searchLog.setString(”deptcode”, “DEPT_CODE GOES HERE”);

IDfTime timeNow = new DfTime();
searchLog.setTime(”starttimeofsearch”, timeNow);
searchLog.setInt(”noofresults”,-1);
setNewValuesForAttribute(”keyword”, queryDesc, ” “, searchLog);

String searchLocations = getSearchSources();
setNewValuesForAttribute(”location”, searchLocations, “,”, searchLog);

searchLog.save();

m_NewSearchLogObjectId = searchLog.getObjectId().getId();
System.out.println(”************ Saved Search Log ************” + objectId);
m_loggedToDB = true;
} catch (DfException e) {
e.printStackTrace();
}

}

private void updateSearchLogObject(){
System.out.println(”### Updating the record”);

Datagrid datagrid = (Datagrid)getControl(”doclistgrid”,

com.documentum.web.form.control.databound.Datagrid.class);
//Get total number of results available from the underlying DataHandler
//Note that a value of -1 indicates that the DataHandler does not support results counting.
int noOfResults = datagrid.getDataProvider().getResultsCount();
System.out.println(”Datagrid noOfResults: ” + noOfResults );
if(noOfResults != -1) {
IDfSession sess = this.getDfSession();

IDfClientX clientx = new DfClientX();
try {
IDfPersistentObject searchLog = (IDfPersistentObject)sess.getObject(
clientx.getId(m_NewSearchLogObjectId));

IDfTime timeNow = new DfTime();
searchLog.setTime(”endtimeofsearch”, timeNow);
searchLog.setInt(”noofresults”,noOfResults);

searchLog.save();
m_loggedNoOfResultsToDB=true;
System.out.println(”************ Updated Search Log ************”);
} catch (DfException e) {
e.printStackTrace();
}
}

private void setNewValuesForAttribute(String attributeName,
String queryString, String delimiter, IDfPersistentObject obj) throws DfException {

StringTokenizer st = new StringTokenizer(queryString, delimiter);
for (int i = 0; st.hasMoreTokens(); i++) {
obj.appendString(attributeName, st.nextToken());
}
}

Thumbnail Server and McAfee Anti-virus Port Clash

I recently installed Documentum Thumbnail Server on a Windows box and I had strange problem. The thumbnail server showed status as “Started” in the Windows Services console. But the DAM refused to show any thumbnails.

To test if the Thumbnail server was running correctly, I used IE to hit this URL: http://localhost:8081/thumbsrv/getThumbnail?

If the thumbnail server was running allright, IE should display a default document icon. Instead I saw the logs of my McAfee Anti-virus. This meant that McAfee was using the port:8081 which is the default port used by Thumbnail server.

Fix:

Since Thumbnail server uses Tomcat internally, I had to change the port to 8082.

a) Using Notepad, open the server.xml in the D:\Documentum\product\5.3\thumbsrv\container\conf
b) Search for “” and in this section for connectors, change the port number ”/> I used 8082 successfully.
c) Restart the thumbnail server
d) Test using http://localhost:/thumbsrv/getThumbnail?

Update the configuration of the thumbnail file-store to change the base_url attribute.
a) Open Documentum Administrator (DA),
b) Look for the file-store - “thumbnail_store_01″
c) View properties and update the base url.
d) Restart the docbase
e) Open DAM and test if thumbnails are being displayed correctly

Back Up Vs Archive

Backup
Secondary copy of information
Used for recovery operations
Improves availability by enabling application to be restored to a specific point in time
Typically short-term (weeks or months)
Data overwritten on periodic basis (monthly)
Not useful for compliance

Archive
Primary copy of information
Available for information retrieval
Adds operational efficiencies by moving fixed/unstructured data out of the operational environment
Typically long-term(months,years,decades)
Data retained for analysis or compliance
Useful for compliance

Registered Tables in Documentum

Registered tables are the tables that are present database which are registered in Documentum, so that it can be accessed using DQL. Basically Registered tables are used when the application needs to access data from the RDBMS within the Documentum. This can be either a Table or a View. The Scenarios where I mostly used registered tables are for providing value assistance for Object attributes. I am not getting into too much of details about Value Assistance here, Value assistance is a list of values that a client program (such as Webtop or a Custom WDK Application) displays at runtime for an object attribute. A user can select a value from this list (or, if allowed, add a new one to it). You can set the Value assistance for an Attribute using DAB (Documentum Application Builder).

As I mentioned above uou can register a Table or a view as a Registered Table, The Registered tables are stored as dm_registered objects in repositories. This extends dm_sysobject. And the r_object_id of this type always starts with 19. The following table lists the attributes of dm_registered

Name Info Description
column_count Integer - Single Number of columns in the table.
column_datatype string(64) - Repeating List of the datatypes of the columns.
column_length. integer R Lengths of the columns that have a string data type
column_name. string(64) - Repeating List of the names of the columns in the table
group_table_permit integer - Single Defines the RDBMS table permit level assigned to the registered table’s group.
is_key. Boolean Repeating Indicates if an index is built on the column
owner_table_permit integer - Single Defines the RDBMS table permit level assigned to the registered table’s owner
synonym_for string(254) - Repeating Name of the table in the underlying RDBMS (can be an Oracle table synonym, or an MS SQL Server or Sybase table alias)
table_name string(64) Single Name of the table.
table_owner string(64) Single Name of the owner of the RDBMS table (the person who created the RDBMS table).
world_table_permit integer - Single Defines the RDBMS table permit level assigned to the world

You should either own the table or have super user privileges to register a table. And since this object is linked with /system cabinet you should have write permission on /system cabinet. This is applicable only if the folder security is enabled in Repository

You cannot version a dm_registered object. And also the changes made to the table are not automatically updated in dm_registered object. So if any changes has been made to the structure of the table or view you should unregister it first and register the table again with changes.

How to Register a Table?
Use the following DQL to register a table. REGISTER TABLE [owner_name.]table_name (column_def {,column_def}) [[WITH] KEY (column_list)][SYNONYM [FOR] ‘table_identification‘] This DQL will return the r_object_id of the newly created dm_registered object. In this owner_name is the name of the table owner. table_name is the name of the RDBMS table. column_def defines the columns in the registered table.

column_def arguments should have following syntax column_name datatype [(length)] the valid values for types are float, double, integer, int, char, character, string, date, time.

Length should be specified for character, char, or string data type.

column_list Identifies the columns in the table on which indexes have been built. column_list is usually separated with commas. table_ identification is the name of the table in the Database Example:

REGISTER TABLE “hr.users” (”first_name” CHAR(30), last_name (char 40), “emp_id” INT)KEY (”emp_id”)



Granting Rights
You need to give the permission to the users to access the registered tables. The values for various permission levels are as follows 0 (None): No access 1 (Select): The user can retrieve data from the registered table 2 (Update): The user can update existing data in the registered table4 (Insert): The user can insert new data into the registered table8 (Delete): The user can delete rows from the registered table If a user wants update and insert permissions the value should be 2+4 = 6 , The repository owner also should have the same level of permission in the underlying database to grand those permission to those users. Granting Rights full permission to users in the above example

update dm_registered object set world_table_permit = 15 where object_name = ‘users’;

update dm_registered object set owner_table_permit = 15 where object_name = ‘users’;

update dm_registered object set group_table_permit = 15 where object_name = ‘users’;




How to Unregister a Table?

Use the following DQL to Unregister a Table.

UNREGISTER [TABLE] [owner_name.]table_name In this owner_name is the name of the table owner. table_name is the name of the RDBMS table. You should be the owner of table or super user to do this


Accessing Data from Registered Table

Just like in RDBMS you can access registered table using the following syntax

Select [ATTRIBUTES] from dm_dbo.[REGISTERED_TABLE_NAME] where [CLAUSE]

The Operations such as update/ delete also has the same RDBMS syntax that’s used for a ordinary SQL, Only difference is prefixing dm_dbo to the table name

Example:

Select first_name, last_name, emp_id from dm_dbo.users ;

Sysadmin and Super User

Sysadmin

Create, alter, and drop users and groups
Create, modify, and delete system-level ACLs
Grant and revoke Create Type, Create Cabinet, and Create Group privileges
Create types, cabinets, and printers
Manipulate workflows or work items, regardless of ownership
Manage any object’s lifecycle
Set the a_full_text attribute

The Sysadmin privilege does not override object-level permissions

Super User

Perform all the functions of a user with Sysadmin privileges
Unlock objects in the repository
Modify or drop another user’s user-defined object type
Create subtypes that have no supertype
Register and unregister another user’s tables
Select from any underlying RDBMS table regardless of whether it is registered or not
Modify or remove another user’s groups or private ACLs
Create, modify, or remove system ACLs
Grant and revoke Superuser and Sysadmin privileges
Grant and revoke extended privileges
View audit trail entries

Documentum Vs Sharepoint

1. Sharepoint 2007 is tightly integrated with Office 2007. Documentum has some light integration with Office through Webtop Application Connectors. Documentum has stronger integration with other authoring applications including Dreamweaver, QuarkXPress, and Adobe InDesign.
2. Sharepoint provides various mechanisms to access and modify content when offline (eg Outlook, Access, etc). Documentum only supports offline editing if you install Documentum Desktop application.
3. Sharepoint 2007 supports rights management with Office 2007 natively. Documentum requires you to install Information Rights Manager to have this feature.
4. Both Documentum and Sharepoint provide the ability to create custom object types. However, Sharepoint’s object model does not seem to support object inheritance.
5. Lifecycle features (eg applying actions, defining entry criteria, applying lifecycle to multiple documents, etc) is more extensive in Documentum than in Sharepoint.
6. Documentum security model is more extensive than Sharepoint. Documentum has extended permissions that allow users to perform specific functions (eg change ownership, change state, change permissions, etc).
7. All objects in Documentum are secured using the security model. In Sharepoint only certain objects can be secured (eg web site, list, folders, documents, etc).
8. Content can be only published to Sharepoint site; however, if content needs to publish outside of MOSS repository, this requires custom coding. Content can be published to any website using Documentum Site Caching and Site Delivery Services. Documentum also has portlets for various portal vendors that allow those portals to access content that is stored in Documentum repository.
9. The obvious - Sharepoint only runs on Windows using Microsoft SQL Server. If you are enterprise standard is UNIX/Linux or Oracle/DB2, then Sharepoint is not a valid option. Documentum is OS and database agnostic. Documentum is supported on various OS and database configurations.
10. The next obvious – Sharepoint is built on ASP.NET; thus, customizations are done via .NET framework. Documentum is built on DFC, which is built on Java. You should consider the development and support skills of your staff when considering which system to choose.
11. Content Storage - Sharepoint stores content within the SQL Server database. This allows Sharepoint to utilize SQL Server native search capabilities. This also means that backup of content is solely dependent on backing up of the database. Documentum stores content on a file storage system and content metadata in any database. This architecture allows for multi-server single docbase configuration. Since content is stored on file system, you can also create a mix storage architecture composed of SAN, NAS, RAID, tape, etc