Display Custom Attributes in Webtop Object Listing Components
| January 2006 | |
|
Software Environment
| Feature | Tested on |
| Operating System | Windows 2000 Server SP4 |
| Compiler | Sun JDK 1.4.2_08 |
| Runtime | Sun JRE 1.4.2_08 |
| DFC | 5.3 SP1 |
| WDK | 5.3 SP1 |
| Webtop | 5.3 SP1 |
| Content Server | 5.3 SP1 |
Abstract
This article discusses the process of displaying custom attribute columns in the webtop object listing components such as objectlist and homecabinet_classic. A sample implementation of the WDK interface com.documentum.web.form.control.databound.ICustomAttributeDataHandler, used to display custom attributes, is provided.
Introduction
Webtop/WDK provides components to display objects within a folder/cabinet. Examples of such components are the objectlist, which is used to show the contents of a cabinet/folder in the classic view and homecabinet_classic, which is used to show the contents of a user's home cabinet in the classic view. The XML configuration files for these components configure the object attributes (columns) to be displayed in the list. The components come with a pre-configured list of attributes such as size and format. However, sometimes it becomes necessary to show custom attributes of a user type.
To display custom attributes in the object listing components, an implementation of com.documentum.web.form.control.databound.ICustomAttributeDataHandler interface must be provided to WDK. The implementation of this interface is responsible for extracting the values of the custom attributes. WDK invokes the implementation per-page of the listing. For example, if the total contents of a folder being displayed are 2000 and only 10 are being displayed on the page, then WDK calls the ICustomAttributeDataHandler implementation only for the 10 items instead of 2000. It will call the next 10 when the user pages to the next 10 objects. This results in a more efficient means of extracting custom attribute values.
Steps
- Create a repository type called my_type with supertype dm_document and two attributes called cust_attr1 and cust_attr2 of type string and int respectively.
-
Create a new class called com.documentum.devprog.test.TestCustomAttributeDataHandler that implements the interface ICustomAttributeDataHandler.
public class TestCustomAttrDataHandler implements ICustomAttributeDataHandler
{
public String[] getRequiredAttributes()
{
}
public void getData(IDfSession sess, ICustomAttributeRecordSet rs)
{
}
}
|
-
Now add the implementation for the getRequiredAttributes() method. This method is called by WDK to determine what attributes this implementation needs in order to get the custom attribute values. In our case, we need the r_object_id and r_object_type. We need r_object_type to determine the objects in the file listing of type 'my_type' because the object types may vary and we need to extract the custom attributes of only 'my_type' objects.
public class TestCustomAttrDataHandler implements ICustomAttributeDataHandler
{
private String[] reqAttrs = {"r_object_id","r_object_type"};
public String[] getRequiredAttributes()
{
DfLogger.debug(this,"GetReqAttrs called",null,null);
return reqAttrs;
}
public void getData(IDfSession sess, ICustomAttributeRecordSet rs)
{
}
}
|
-
Next, we add the implementation of the getData() method. This method is called by WDK to obtain the values of the custom attributes. The ICustomAttributeRecordSet contains the set of all objects being currently displayed and the required attributes that we requested for each of those objects. First we discuss the simplified implementation steps -
-
Get object ids of all objects in the recordset whose type is my_type. To do this, we call the getRows() method on the ICustomAttributeRecordSet argument. This overloaded method takes two parameters. The first parameter specifies the attribute to look for (r_object_type) and the second specifies the attribute value (my_type). Thus, this method returns all row indexes whose r_object_type attribute value equals 'my_type'
int[] ids = rs.getRows("r_object_type","my_type");
|
-
Next, for each of these objects get the object id and using that extract the custom attributes.
for(int i=0;i<ids.length;i++)
{
...
String objId = rs.getAttributeValue(ids[i],"r_object_id");
...
//Query and get the custom attrs.
}
|
-
Finally, you need to set the custom values using the method
ICustomAttributeRecordSet#setCustomAttributeValue(rowIndex,CUST_ATTR,val);
Here is the complete code -
package com.documentum.devprog.test;
...
//imports
...
public class TestCustomAttrDataHandler implements ICustomAttributeDataHandler
{
private String CUST_ATTR1 = "cust_attr1";
private String CUST_ATTR2 = "cust_attr2";
private String[] reqAttrs = {"r_object_id","r_object_type"};
public String[] getRequiredAttributes()
{
DfLogger.debug(this,"GetReqAttrs called",null,null);
return reqAttrs;
}
public void getData(IDfSession sess, ICustomAttributeRecordSet rs)
{
DfLogger.debug(this,"getData called :",null,null);
int[] ids = rs.getRows("r_object_type","my_type");
for(int i=0;i<ids.length;i++)
{
StringBuffer bufQual = new StringBuffer(24);
bufQual.append("select cust_attr1,cust_attr2 from my_type where r_object_id='");
String objId = rs.getAttributeValue(ids[i],"r_object_id");
bufQual.append(objId).append("'");
String strQuery = bufQual.toString();
IDfClientX clientX = new DfClientX();
IDfQuery queryObj = clientX.getQuery();
queryObj.setDQL(strQuery);
IDfCollection coll = null;
try
{
coll = queryObj.execute(sess,IDfQuery.DF_READ_QUERY);
if(coll.next())
{
String val1 = coll.getString(CUST_ATTR1);
if(val1 != null)
{
rs.setCustomAttributeValue(ids[i],CUST_ATTR1,val1);
}
String val2 = coll.getString(CUST_ATTR2);
if(val2 != null)
{
rs.setCustomAttributeValue(ids[i],CUST_ATTR2,val2);
}
}
}
catch(DfException dfe)
{
DfLogger.error(this,"Error getting custom attrs for my_type",null,dfe);
}
finally
{
if(coll != null)
{
try{coll.close();}catch(DfException dfe2){}
}
}
}
}
}
|
-
Compile the class with the compilation target set to VIRTUAL_ROOT/web-inf/classes. To read more about setting up a compilation environment refer to the WDK Developer Guide for an example of setting up NetBeans or to the developer site for an example of setting up Eclipse
-
Next, we need to tell the WDK framework about this attribute handler. This is done by a configuration in the app.xml. Open the VIRTUAL_ROOT/webcomponent/app.xml file and copy the XML element(including contents) <custom_attribute_data_handlers>. Open the VIRTUAL_ROOT/custom/app.xml file and paste this section within the <application> tags.
Note that if you have previously added a custom attribute handler, copy this section from the webtop layer - VIRTUAL_ROOT/webtop/app.xml instead.
-
Now within the <custom_attribute_data_handlers> section of the VIRTUAL_ROOT/custom/app.xml add the following -
<custom_attribute_data_handler>
com.documentum.devprog.test.TestCustomAttrDataHandler
</custom_attribute_data_handler>
|
-
Next,we need to configure the <columns> element in the homecabinet_classic and objectlist components of the Webtop layer to specify the custom attributes. To do this, create two component definitions in the custom layer.
Note:If you using the WDK Eclipse Plugin,also refer to a later section on configuring columns using the plugin
<component
extends="homecabinet_classic:/webtop/config/homecabinet_classic_component.xml"
id="homecabinet_classic">
</component>
|
<component extends="objectlist:/webtop/config/objectlist_component.xml"
id="objectlist">
</component>
|
-
Copy the <columns> element from files VIRTUAL_ROOT/webcomponent/config/navigation/homecabinet/homecabinet_list_component.xml and VIRTUAL_ROOT/webcomponent/config/navigation/doclist/doclist_component.xml and paste in the custom definitions for homecabinet_classic and objectlist created in the previous step.
-
Paste the following column definitions within the custom columns element of both the homecabinet_classic and objectlist components. This will configure the objectlist and homecabinet_classic components to display the custom attribute columns. You will need to customize and add the column definitions to all the Webtop components that display the object lists (e.g. homecabinet_streamline, streamline components).
<column>
<attribute>cust_attr1</attribute>
<label>My Cust Attr1</label>
<visible>true</visible>
</column>
<column>
<attribute>cust_attr2</attribute>
<label>My Cust Attr2</label>
<visible>true</visible>
</column>
|
-
Restart the app server or reload the Webtop/WDK webapp.
-
Import some documents into the repository and set their type as 'my_type'. Set the values of the custom attributes. The custom attributes should get displayed in the object listing components.

Fig - Custom Attributes in the objectlist component
Displaying Non-Repository Attributes
Although the example above shows how to display values of a repository type's attributes, the ICustomAttributeDataHandler interface implementation can be used to set any value. Its not necessary that the custom attributes be attributes of a repository type. They can be attributes whose values are calculated based on the environment (e.g. obtained from a database table). For example, the following adds an additional attribute to the columns definition that is not a repository type's attribute and the interface implementation sets the attributes value to ["Hello World " + r_object_id], irrespective of repository type(i.e. for all objects in the recordset).
<column>
<attribute>hello_world_attr</attribute>
<label>Hello World Attr</label>
<visible>true</visible>
</column>
public class TestHelloWorldAttr implements ICustomAttributeDataHandler
{
private String[] reqAttrs = {"r_object_id"};
public String[] getRequiredAttributes()
{
return reqAttrs;
}
public void getData(IDfSession sess, ICustomAttributeRecordSet rs)
{
int rowCnt = rs.getCount();
for(int i=0;i<rowCnt;i++)
{
String objId = rs.getAttributeValue(i,"r_object_id");
rs.setCustomAttributeValue(i,"hello_world_attr","Hello World: " + objId);
}
}
}
|

Fig - Non-Repository Attribute
Using the WDK Eclipse Plugin for Configuring Columns
If you are using the WDK Eclipse plugin for configuring the columns, here are the steps -
-
Create two new component definitions in the custom layer (right-click on Components node and click on 'New Component') of ids 'homecabinet_classic' and 'objectlist'. For these choose the parents as 'homecabinet_classic' and 'objectlist' from the webtop layer respectively. Be sure to select the non-scoped parents.

Fig - Components in the Custom layer

Fig - Choose Parent
-
For each, click on the 'Insert From Parent' button and choose the 'columns' element.This will copy the 'columns' element from the parent definition. You can now add the additional column definitions to the copied columns element.

Fig - Insert 'columns' from parent
-
For each definition, switch to the 'XML' tab of each custom config definition, add the column definitions in the XML there and save (CTRL+S).

Fig - Edit the XML definition
Download
Download the Java source and class file. The download also contains the config files. However, we recommend that you create these in your environment using the ones in the package for reference.
Acknowledgements
Many thanks to Linda Wong and Zaka Ashraf from WDK Engineering for suggesting this article. Linda also reviewed the article and examples for technical accuracy.
|