Using Java reflection to reduce Code and Development time in DFS


 

Java reflections are one of the most powerful API’s of Java Language, this can be used to reduce code significantly.

Most of the Current Enterprise application consists of different layers and they use Value objects to transfer data from one layer to another. An inefficient way of using getters and setters of the attributes of Value objects can increase code and development time of application. Effective use of reflection can reduce code and development time significantly.

So let’s take a Scenario,  I have an Object type MyObjectType extending from dm_document with 50 additional attributes, so dm_document as of Documentum 6.5 has 86 attributes adding additional 50 attributes that means we have 139 attributes for this object type. Consider a standard Web Application using DFS behind which needs to manipulate (add or edit) instances of this object type, The Service needs to add all these attributes to the PropertySet  of the DataObject representing that instance. Then need to call the appropriate service.

 

Considering that the bean instance name of MyObjectType is myObjectBean the Standard code will  be something like this

  ObjectIdentity objIdentity = new ObjectIdentity("myRepository");
  DataObject dataObject = new DataObject(objIdentity, "dm_document");
  PropertySet properties = dataObject.getProperties();
  properties.set("object_name", myObjectBean.getObject_Name());
  properties.set("title", myObjectBean.getTitle()); 
  // omited for simplicity


  objectService.create(new DataPackage(dataObject), operationOptions);

 

In the above code you have to explicitly set individual attributes for the object, the more the number of attributes the more complex and messy code.

Take another Example, where you have to retrieve an Object information and pass it over to the UI layer.

 myObjectBean.setObject_name(properties.get("object_name").getValueAsString());
 myObjectBean.setTitle(properties.get("title").getValueAsString());
 myObjectBean.setMy_Custom_Property(properties.get("my_custom_property").getValueAsString());

This operation can be more complex if you decide to use match the Data Type of your bean with the Object type.

 

So what is the best approach to reducing this complexity? the answer is the effective use of reflection API.

Let’s take a step to step approach to handle this issue.

To understand this better consider the below as the attributes of mycustomobjecttype

 

Attribute Name Attribute Type
first_name String
last_name String
age integer
date_purchased time
amount_due double
local_buyer boolean

 

Java Bean

Create a Java Bean that matches the Object Type

 public class Mycustomobjecttype {
  protected String first_name ;
  protected String last_name  ;
  protected int age;
  protected Date date_purchased  ;
  protected double amount_due  ;
  protected boolean local_buyer ;
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
  public double getAmount_due() {
    return amount_due;
  }
  public void setAmount_due(double amount_due) {
    this.amount_due = amount_due;
  }
  public Date getDate_purchased() {
    return date_purchased;
  }
  public void setDate_purchased(Date date_purchased) {
    this.date_purchased = date_purchased;
  }
  public String getFirst_name() {
    return first_name;
  }
  public void setFirst_name(String first_name) {
    this.first_name = first_name;
  }
  public String getLast_name() {
    return last_name;
  }
  public void setLast_name(String last_name) {
    this.last_name = last_name;
  }
  public boolean isLocal_buyer() {
    return local_buyer;
  }
  public void setLocal_buyer(boolean local_buyer) {
    this.local_buyer = local_buyer;
  }
}

Getting the Values from PropertySet (Loading Java Bean)

……

List<DataObject> dataObjectList = dataPackage.getDataObjects();
DataObject dObject = dataObjectList.get(0);
Mycustomobjecttype myCustomObject = new Mycustomobjecttype();
populateBeanFromPropertySet(dObject.getProperties(),myCustomObject);

……

// See the Reflection in Action here 
public void populateBeanFromPropertySet(PropertySet propertySet, Object bean)
  throws Exception {
 BeanInfo beaninformation;
 beaninformation = Introspector.getBeanInfo(bean.getClass());
 PropertyDescriptor[] sourceDescriptors = beaninformation.getPropertyDescriptors();
 for (PropertyDescriptor descriptor : sourceDescriptors) {
     Object result = null;
     String name = descriptor.getName();
    if (!name.equals("class")) {
      if (propertySet.get(name) != null) {
        if (descriptor.getPropertyType().getName().equals("int")) {
          result = new Integer(propertySet.get(name)
              .getValueAsString());
        } else if (descriptor.getPropertyType().getName().equals("double")) {
          result = new Double(propertySet.get(name).getValueAsString());
         } else if (descriptor.getPropertyType().getName().equals("boolean")) {
          result = new Boolean(propertySet.get(name).getValueAsString());
         } else if (descriptor.getPropertyType().getName().equals("java.util.Date")) {
          DateProperty dat = (DateProperty)propertySet.get(name);
          result = dat.getValue();
        }else {
          // none of the other possible types, so assume it as String
          result = propertySet.get(name).getValueAsString();
        }
        if (result != null)
          descriptor.getWriteMethod().invoke(bean, result);
      }
     }
  }
}

Setting Values to Property Set

 

public DataPackage createContentLessObject(Mycustomobjecttype myCustomType) throws Exception {
ObjectIdentity objectIdentity = new ObjectIdentity("testRepositoryName");
DataObject dataObject = new DataObject(objectIdentity, myCustomType.getClass().getName());
PropertySet properties = populateProperties(myCustomType);
properties.set("object_name",myCustomType.getFirst_name()+myCustomType.getLast_name() );
dataObject.setProperties(properties);
DataPackage dataPackage = new DataPackage(dataObject);
OperationOptions operationOptions = new OperationOptions();
return objectService.create(dataPackage, operationOptions);
}

 

// Reflection in Action  
public PropertySet populateProperties(Object bean)throws Exception {
BeanInfo beaninfo;
PropertySet myPropertyset = new PropertySet();
beaninfo = Introspector.getBeanInfo(bean.getClass());  
PropertyDescriptor[] sourceDescriptors = beaninfo
      .getPropertyDescriptors();
  for (PropertyDescriptor descriptor : sourceDescriptors) {
    String propertyName = descriptor.getName();
    if (!propertyName.equals("class")) {
        // dont set read only attributes if any
       // example r_object_id 
       if (!propertyName.startsWith("r")) {
        Object value = descriptor.getReadMethod().invoke(bean);
       if (value != null) {
          myPropertyset.set(propertyName, value);
        }
      }
   }
 }
  return myPropertyset;
}

Few Important Object Types in Documentum


 

 

Documentum is an Object Oriented Content Management Systems. Everything in Documentum is considered as Objects, This includes all the things that user manipulates, or the content server saves. From the User to Document, everything in Documentum is different type of Object. The whole Object types in Documentum has been structured in a Hierarchal model. Means All the Attributes from the super types are extended to the sub types. In other sense the attributes of Super types are visible and accessible from the Subtypes.

 

Lets see some of the important and most commonly used object types here. 

 

Note: This is just to give an insight of Documentum Object model. Please read Object Reference Manual for very detailed information on All Object types and its attributes.

Persistence Object 

This type is the super type of all the object types that are saved in Documentum. Each time user creates an object instance of Persistence object type they are objects stored in the repository, this can be retrieved at a later point of time from the Content server.

 

This Object type is an internal type and you cannot create an instance of it.  There are only 3 attributes for this object type they are. These attributes are extended to all the object types across the Documentum.

 

1)      r_object_id
A Unique ID of an object. Content server generates this ID when you create an object of any type. There are some interesting aspects about r_object_id. r_object_id is 16 characters long and its alpha numeric.

The characters from position 01 to 02 indicate the object type tag (09 = document, 0b = folder, etc.).

The characters from position 03 to 08            Repository id (Same for every object in a Repository, but different for each Repository)     

The characters from position 09 -to 16            is unique identifier for this object

 

Consider the following r_object_id 09012a5b80075dc2 in this 09 is the Object type Tag, 012a5b is the repository ID and 80075dc2 is the unique id that represents this object.

2)      i_vstamp
This property is basically used for versioning, each time you save changes to the object the value of this property increases by 1 and this also helps to check the concurrent modification of object.

3)      i_is_replica
This property of object that indicates whether that object is replica of  an object in a remote repository

 

Sys Object (extended from Persistence Object) (dm_sysobject)

Most of the commonly used object types are extended from this object type. Most common Subtypes include Document, Folder, and Cabinet etc.

There are 4 important characteristics for this Object type. They are

1)      Only dm_sysobject and its subtypes can be defined as shareable

2)      They can have permissions associated (Attach ACL).

3)      Sys object can belongs to a folder (Exception Cabinet – Cabinet cannot belong to a folder)

4)      Sys object can have content attached to it.

ACL  (extended from Persistence Object) (dm_acl)

This object type plays a very vital role in implementing security to the Documentum server if the security model of Content Server is set to ACL. All ACL objects r_object_id starts with letters 45

User (extended from Persistence Object)(dm_user)

This stores all the information about user in a Documentum repository, Only a Super user or Sys Admin can create/activate/delete/deactivate a user. All User Object’s r_object_id starts with letters 11

Group (extended from Persistence Object)(dm_group)

A group is the group of users and it can include another groups also.  This object stores information about a specific group, which includes r_object_id of all the member users, groups. This has identifier which determines whether it’s a group or a role. All the group objects has r_object_id starting with 12

Document (extended from Sys Object)(dm_document)

Documents represent a real document in Repository; it can be associated with 0 or more content objects also.  A Document may be a real document or virtual document. All objects of this type has a r_object_id starting with 09

Folder (extended from Sys Object)(dm_folder)

Folders are basically used to organize contents. All the sys objects that are created should be linked with at least one folder or a Cabinet. An Object can be linked with multiple folders also. All objects of this type has a r_object_id starting with 0b

Cabinet (extended from Sys Object)(dm_cabinet)

Cabinet is a special type of folders and its used to organize sys object in a repository. Cabinets are the highest in the Folder Hierarchy in Documentum. A Cabinet cannot be placed inside a Cabinet or a Folder and that makes it special. All objects of this type has a r_object_id starting with 0c

Registered (extended from Sys Object)(dm_registered)

Represents a Registered table in a RDBMS in Documentum. It has the table, name, column names and it s data type saved.  All objects of this type has a r_object_id starting with 19

  

Object types that are not saved in Repository

There are few Object types in Documentum, which are not to be saved in the repository. These are some object types that are created on runtime and destroyed as its use is over. Here is the list of those object types.

 

Client config (New in D6)

A Client config object is created at every time when DFC is initialized. This has all the properties in the dfc.properties file.

Connection Config

This type describes a session’s connection to a specific repository

Docbroker Locator

A docbroker locator object contains information about each connection broker that the

client DMCL can access

Docbase Locator

This has information all repositories registered with a connection broker

Server Locator

A server locator object has information about all the servers registered to a connection broker

Session Config

Contains information about an open repository session

 

Download this Study Note (PDF)

Installation Issues of Documentum 6 SP1 Content Server on AIX


We had done a D6 SP1 installation few days ago and ran into some issues, I thought I will share my expereince with you all so that you know the issues that you may face during the installation of content server on AIX.

 As we stared with the installation of Content Server on our AIX system (5.3) we were hit with the following error

“The /tmp filesystem needs 1GB where it has 0 GB Available”  We had more than 1 GB space in both /var/tmp and /tmp.

During this I found an interesting thing that even the D6 Installer guide has lots of typos in it. It says /tmp some place then someother place it says /temp should have 1 GB  free space !!!!

If you are hit with this issue there is a work around,  You have to add the tmp directory location as parameter to the installer.  

That means you have to run the installer with following command line

serverAixSuiteSetup.bin -is:tempdir TMP_DIR

Where TMP_DIR should point your tmp directory which has more than 1 GB Space.

Another interesting issue is Though the D6 Installer guide in page number 143 says that if you run dm_launch_server_config_program.sh it will set the environment variables such as LIBPATH etc that doesnt really do that. So if you are installing D6 CS on AIX after completing the installtion make sure sure that you edit the profile of install owner and add these paths to it

Happy Installing !!!