Hello Community,
I am having trouble implementing my TBO. I have created the custom type "xa_content" that is a subtype of dm_document. The type has several string attributes that need to be converted to uppercase before being save/stored in the docbase. The strings can be variable length so the "UUUUUU" mask won't work here I also have a special case in which one of the attributes needs to be tested for uniqueness. Please see below the error message for my TBO implementation class.
I currently get the following error in Webtop after selecting my custom document type and then clicking Next:
An error has occurred.
invokeMethod() failed while calling: onNextComponent
com.mycompany.tbo.CustMetadata cannot be cast to com.documentum.fc.client.IDfType
After closing this window, press the Refresh or Reload button on your browser to continue.
Hide Details
Stack Trace:
java.lang.ClassCastException: com.mycompany.tbo.CustMetadata cannot be cast to com.documentum.fc.client.IDfType
at com.mycompany.tbo.CustMetadata.modifyAttributes(CustMetadata.java:66)
at com.mycompany.tbo.CustMetadata.doSave(CustMetadata.java:57)
at com.documentum.fc.client.DfPersistentObject.saveEx(DfPersistentObject.java:918)
at com.documentum.fc.client.DfPersistentObject.save(DfPersistentObject.java:913)
at com.mycompany.tbo.CustMetadata___PROXY.save(CustMetadata___PROXY.java)
at com.documentum.webcomponent.library.create.CreateService.createObject(CreateService.java:341)
at com.documentum.webcomponent.library.create.NewDocument.createNewObject(NewDocument.java:466)
at com.documentum.webcomponent.library.create.NewDocContainer.createObject(NewDocContainer.java:265)
at com.documentum.webcomponent.library.create.NewContainer.onNextComponent(NewContainer.java:153)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.documentum.web.form.FormProcessor.invokeMethod(FormProcessor.java:1652)
at com.documentum.web.form.FormProcessor.invokeMethod(FormProcessor.java:1506)
at com.documentum.web.form.FormProcessor.fireActionEvent(FormProcessor.java:1311)
at com.documentum.web.form.RecallOperation.execute(RecallOperation.java:101)
at com.documentum.web.form.FormProcessor.processAction(FormProcessor.java:120)
at com.documentum.web.form.FormAction.processAction(FormAction.java:107)
at com.documentum.web.env.WDKController.doStartRequest(WDKController.java:238)
at com.documentum.web.env.WDKController.processRequest(WDKController.java:124)
at com.documentum.web.env.WDKController.doFilter(WDKController.java:115)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:60)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3748)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3714)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2283)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2182)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1491)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:256)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:221)
This is my first attempt at coding a TBO, so any pointers would be much appreciated.
package com.mycompany.tbo;
import com.documentum.fc.client.DfDocument;
import com.documentum.fc.client.DfQuery;
import com.documentum.fc.client.IDfCollection;
import com.documentum.fc.client.IDfQuery;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSysObject;
import com.documentum.fc.client.IDfType;
import com.documentum.fc.common.DfException;
import com.documentum.fc.common.DfLogger;
import com.documentum.fc.common.IDfValue;
public class CustMetadata extends DfDocument implements ICustMetadata {
public String getVendorString() {
return "My Company";
}
public String getVersion() {
return "1.0";
}
public boolean isCompatible(String arg0) {
return false;
}
public boolean supportsFeature(String arg0) {
return false;
}
public void setDoctype(String doctype) throws DfException {
setString("xa_content", doctype);
}
public String getDoctype() throws DfException {
return getString("xa_content");
}
protected synchronized void doSave(boolean saveLock, String versionLabel, Object[] extendedArgs)
throws DfException {
DfLogger.info(this, "doSave called for object with id: {0}", new String [] {getObjectId().toString()}, null);
ICustMetadata xaContent = (ICustMetadata) this;
modifyAttributes(this.getSession(), xaContent);
super.doSave(saveLock, versionLabel, extendedArgs);
}
/**
*
* @param dfSession
* @param metadataObj
* @throws DfException
*/
private void modifyAttributes(IDfSession dfSession, IDfSysObject metadataObj) throws DfException {
for (int i = 0; i < metadataObj.getAttrCount(); i++){
//Get the attribute's data type at current position
int attrDataType = ((IDfType) metadataObj).getTypeAttrDataTypeAt(i);
//Get attribute's type name at current position
String attrName = ((IDfType) metadataObj).getTypeAttrNameAt(i);
//Get attribute's value at current position
IDfValue attrValue = metadataObj.getValueAt(i);
//Is repeating attribute
boolean repeat = ((IDfType) metadataObj).isTypeAttrRepeatingAt(i);
//Test if the attribute's name contains "xa_"
if (attrName.contains("xa_")){
//Test if it's a string
switch (attrDataType) {
case IDfType.DF_STRING:
setAttributeToUpper(repeat, attrName, attrValue, metadataObj);
break;
case IDfType.DF_UNDEFINED:
setAttributeToUpper(repeat, attrName, attrValue, metadataObj);
break;
} //end switch
}//end if
//Special case - xa_barcode is a string and repeating - test if unique
if (attrName.equals("xa_barcode")){
//Test for uniqueness
findUniqueAttribute(attrName, attrValue, metadataObj);
}
}//end for
}
/**
* Method to deal with repeating attributes. If the attribute repeats, then each attribute is changed to upper case.
* Otherwise the single value is set to upper case.
* @param IsRepeating
* @param attrName
* @param value
* @param document
*/
private void setAttributeToUpper(boolean isRepeating, String attrName, IDfValue value, IDfSysObject document) throws DfException {
if (isRepeating){
for (int i = 0; i < document.getValueCount(attrName); i++) {
document.setRepeatingString(attrName, i, value.toString().toUpperCase());
document.save();
}//end for
}
else {
document.setRepeatingString(attrName, 0, value.toString().toUpperCase());
document.save();
}
}
/**
* Method to test if an attribute is unique and throws an exception if the value is not unique. Handles repeating attribute.
* @param attrName
* @param attrValue
* @param document
*/
private void findUniqueAttribute(String attrName, IDfValue attrValue, IDfSysObject document) throws DfException {
String docType = document.getTypeName();
StringBuffer sbuf = new StringBuffer();
sbuf.append("select count('" + attrName + "') as cnt " +
"from '" + docType + "' where any '" + attrName + "' ='" + attrValue + "' " +
"group by '" + attrName + "' having count('" + attrName + "') > 1 " +
"order by '" + attrName + "' enable(row_based)");
IDfQuery query = new DfQuery();
query.setDQL(sbuf.toString());
IDfCollection collection = query.execute(document.getSession(), IDfQuery.EXECREAD_QUERY);
if (collection.next()) {
while (collection.next()) {
int result = Integer.parseInt(collection.getRepeatingString("cnt", 1)); //cnt = the count column and 1 is the index value of the result which should always be 1 (returned 1 row).
if (result > 1) {
attrValue = null;
document.save();
//throw warning
throw new IllegalArgumentException("The value " +attrValue+ "is not unique.");
}
document.save();
}
}
collection.close();
}
}
Thank you!
-Sean