Custom Workflows

Joe_Chorba
Joe_Chorba Member
edited August 29, 2012 in Documentum #1

Ok...we have some custom options that need to happen when we run through a workflow, like changing lifecycles and permission. I cannot find for the life of me how to do this?

I have our custom java class, based from when we were running 5.3 SP5, but we are upgrading to 6.7 (on new machines).

Our Content Server is a SPARC 10 Solaris unit, and our Web Server is a Web Server 2008 unit.

I've created the workflows in the web client that Documentum has pointing to the "cmsworkflowmethod" (custom class) for each of the automatic activities, I created a method through our DocApp for "cmsworkflowmethod" pointing to the CMSWorkflow class...but I'm not exactly sure if I have it right? I've looked at some of the documentation, but I cannot seem to find a workflow example with customization in it. I'm not sure if my methods in the docapp are created correctly or not, I'm not sure where to put the methods on the Web / Content Server.

Any help would be much appreciated. IF you can think of a way that I don't need to use custom code to do the workflows (changing lifecycles and permissions) that would work too.

Though I think my supervisor would prefer workflows customizations...

Thanks.

Joe

If this needs more information, please let me know. I'll provide everything I can.

I pretty much have a week to get workflow working properly.

Comments

  • prabhu
    prabhu Member
    edited August 27, 2012 #2

    There are many activity templates available to accomplish the tasks which you mentioned like applying ACL, chaning state of the lifecycle, etc .. you can see this in left side panel of process builder ... and if those templates are not gud enuf, you may very well write custom code and deploy in JMS to use it in a workflow automatic activity

  • Joe_Chorba
    Joe_Chorba Member
    edited August 27, 2012 #3

    With the activity templates to change ACL and lifecycle, are those done in workflow? If so, can you explain how? I didn't see them.

  • DCTM_Guru
    DCTM_Guru Member
    edited August 27, 2012 #4

    Activities templates are part of Process Builder, not Workflow Manager.  Process Builder is new version of WFM that has a lot more capabilities; it requires additional license.

  • Joe_Chorba
    Joe_Chorba Member
    edited August 27, 2012 #5

    Great, so where on the Content Server do I install these custom java classes so that they will work with workflow?

  • prabhu
    prabhu Member
    edited August 29, 2012 #6

    please refer to process builder development guide .. it has all the details you are looking for ..

  • Joe_Chorba
    Joe_Chorba Member
    edited August 29, 2012 #7

    While I appreciate the comments, I don't think anyone else is listening to the question. We are not using Process Builder. We are using the workflow manager. This is what I'm trying to get to work. I've contact EMC about getting process builder, but they have not gotten back to me yet. In the meantime, I need to find a way to make the workflow that we've been using for years on 5.3 work on 6.7.

    I found where it goes, though some of the documentation says that location is depricated. When I start the Java Method Server, it says that it gets the class files from the $DOCUMENTUM/dba/java_methods folder, so I placed my class files here. It still doesn't work.

  • bacham2
    bacham2 Member
    edited August 29, 2012 #8

    Even though deprecated, the location $DOCUMENTUM/dba/java_methods should still work.

    Make sure that your dm_method is using the Java Method Server. Checkout method dm_noop_auto_method_java if you need an example.

  • Joe_Chorba
    Joe_Chorba Member
    edited August 29, 2012 #9

    Here's an image of the method

    method.gif

    here's a copy of my code....

    package com.gdais.custom.Workflow;

    /*
    *   
    * @class name: CMSWorkflow
    *    Called by workflow automatic activity.  This class processes the
    *    child of the workitem document.  For child components of
    *    the mini-build template, promote the lifecycle state, and set permissions
    *    according to current state and CMS Workflow requirements. 
    */

    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;

    import com.documentum.fc.client.DfClient;
    import com.documentum.fc.client.IDfActivity;
    import com.documentum.fc.client.IDfClient;
    import com.documentum.fc.client.IDfCollection;
    import com.documentum.fc.client.IDfSession;
    import com.documentum.fc.client.IDfSessionManager;
    import com.documentum.fc.client.IDfSysObject;
    import com.documentum.fc.client.IDfVirtualDocument;
    import com.documentum.fc.client.IDfVirtualDocumentNode;
    import com.documentum.fc.client.IDfWorkitem;
    import com.documentum.fc.common.DfException;
    import com.documentum.fc.common.DfId;
    import com.documentum.fc.common.DfLogger;
    import com.documentum.fc.common.DfLoginInfo;
    import com.documentum.fc.common.IDfId;
    import com.documentum.fc.common.IDfLoginInfo;
    import com.documentum.mthdservlet.IDmMethod;

    public class CMSWorkflow implements IDmMethod {
    /**
      * @param args
      */
    protected IDfSessionManager m_sessionMgr = null;
    protected String m_docbase = null;
    protected String m_userName = null;
    protected String m_workitemId = null;
    protected String m_ticket = null;
    protected String m_packageID = null;
    protected String m_TaskName = null;
    private String m_domain = null;

    private static final String USER_KEY = "user";
    private static final String DOCBASE_KEY = "docbase_name";
    private static final String WORKITEM_KEY_2 = "workitemId";
    private static final String TICKET_KEY = "ticket";
    private static final String WORKITEM_KEY = "packageId";

    private IDfId docIdObj; // ID of main document in WF package
    private boolean lifeCycleOverride; // always false in this workflow
    private boolean lifeCycleTestOnly; // default to false

    public void execute(Map params, OutputStream ostream) throws Exception {
      IDfSession session = null;
      IDfId workitemID = null;
      IDfWorkitem workitem = null;
      IDfCollection pkgColl = null;
      lifeCycleOverride = false; // force object promotion
      lifeCycleTestOnly = false; // true to test if object can be promoted

      initWorkflowParams(params); // receive and initialize params
      DfLogger.info("tracing", "STARTING WORKFLOW:", null, null);
      IDfSessionManager sessionManager = login();

      try {
       workitemID = new DfId(m_packageID);
       session = sessionManager.getSession(m_docbase);

       DfLogger.info("tracing", "SESSION ID: "
         + session.getSessionId(), null, null);

       // Get the workitem (task)
       workitem = (IDfWorkitem) session.getObject(workitemID);

       // Acquire the workitem then process the package
       workitem.acquire();

       // This is the partial build (techinfo object)
       pkgColl = workitem.getPackages("");

       if (pkgColl != null) {
        while (pkgColl.next()) {
         IDfActivity m_act = workitem.getActivity();
         m_TaskName = m_act.getObjectName();
         DfLogger.info("tracing", "TASK NAME: "
           + m_TaskName.toString(), null, null);
         int docCount = pkgColl.getValueCount("r_component_id");

         for (int i = 0; i <= (docCount - 1); i++) {
          docIdObj = pkgColl.getRepeatingId("r_component_id", i);
          if (docIdObj != null) {
           DfLogger.info("tracing", "DOCIDOBJ: "
             + docIdObj.getId(), null, null);
           setChildProperties(null, docIdObj, session, ostream);
          }
         }
        }
        pkgColl.close();
       }
       DfLogger.info("tracing", "ENDING WORKFLOW:", null, null);
       workitem.complete();
      } catch (DfException e) {
       ostream.write(e.getMessage().getBytes());
       DfLogger.error("tracing", "Error message : " + e.getMessage(),
         null, null);
       e.printStackTrace(); // spit out to stderr as well
       throw e;
      } finally {
       if (session != null) {
        sessionManager.release(session);
        sessionManager.clearIdentities();
       }
      }
    }

    // get the 5 WF-related parameters always passed in by Server
    protected void initWorkflowParams(Map params) {

      Set keys = params.keySet(); // returns a Set
      Iterator iter = keys.iterator(); // get the iterator
      while (iter.hasNext()) {
       String key = (String) iter.next();
       if ((key == null) || (key.length() == 0)) {
        continue;
       }
       String[] value = (String[]) params.get(key);

       if (key.equalsIgnoreCase(USER_KEY)) {
        m_userName = (value.length > 0) ? value[0] : "";
        DfLogger.info("tracing", "INIT WF PARAM-User Name = : "
          + m_userName, null, null);
       } else if (key.equalsIgnoreCase(DOCBASE_KEY)) {
        m_docbase = (value.length > 0) ? value[0] : "";
        DfLogger.info("tracing", "INIT WF PARAM-Docbase = : "
          + m_docbase, null, null);
       } else if (key.equalsIgnoreCase(WORKITEM_KEY_2)) {
        m_workitemId = (value.length > 0) ? value[0] : "";
        DfLogger.info("tracing", "INIT WF PARAM-Workitem ID = : "
          + m_workitemId, null, null);
       } else if (key.equalsIgnoreCase(WORKITEM_KEY)) {
        m_packageID = (value.length > 0) ? value[0] : "";
        DfLogger.info("tracing", "INIT WF PARAM-Package ID = : "
          + m_packageID, null, null);
       } else if (key.equalsIgnoreCase(TICKET_KEY)) {
        m_ticket = (value.length > 0) ? value[0] : "";
        DfLogger.info("tracing", "INIT WF PARAM-Ticket value = : "
          + m_ticket, null, null);
       }
      }
    }

    // login and return a session manager interface
    protected IDfSessionManager login() throws DfException {
      if (m_docbase == null || m_userName == null || m_ticket == null) {
       return null;
      }

      // now login
      IDfClient dfClient = DfClient.getLocalClient();
      if (dfClient != null) {
       IDfLoginInfo li = new DfLoginInfo();
       li.setUser(m_userName);
       li.setPassword(m_ticket);
       li.setDomain(null);

       IDfSessionManager sessionMgr = dfClient.newSessionManager();
       sessionMgr.setIdentity(m_docbase, li);
       return sessionMgr;
      }
      return null;
    }

    // This method sets properties of applicable virtual document components.
    // Applicable objects
    // include those with the MRU_Development lifecycle applied. Recursively
    // Walk the VD (minibuild)
    // tree and set object permissions and lifecycle states.
    private void setChildProperties(IDfVirtualDocumentNode vdNode,
       IDfId docObjID, IDfSession session, OutputStream ostream)
       throws DfException, IOException {
      try {
       if (m_docbase.equalsIgnoreCase("devtest")) {
        m_domain = m_docbase;
       } else if (m_docbase.equalsIgnoreCase("sp23fdcms")) {
        m_domain = m_docbase;
       }
       // get the root object
       if (vdNode == null && docObjID != null) { // for Root node only
        IDfVirtualDocument vDoc = null;
        IDfSysObject m_obj = (IDfSysObject) session.getObject(docObjID);
        if (m_obj != null) {
         // process (vdNode) root node
         vDoc = m_obj.asVirtualDocument("CURRENT", false);
         vdNode = vDoc.getRootNode();
         // DfLogger.info("tracing",
         // "setChildProperties: ROOT OBJ NAME= " +
         // m_obj.getObjectName(),null,null);
        }
       }

       IDfVirtualDocumentNode childNode = null;

       // # of child nodes of current (vdNode) virtual document node
       int childCnt = vdNode.getChildCount();

       // update children objects
       for (int i = 0; i <= (childCnt - 1); i++) {
        childNode = vdNode.getChild(i);
        IDfSysObject m_childObj = childNode.getSelectedObject();
        // String nameOfAcl = m_childObj.getACLName();
        // DfLogger.info("tracing", "ACL NAME: " + nameOfAcl, null,
        // null);

        // Make sure no system objects are processed
        if (m_childObj.getBoolean("a_is_template") == false
          && !(m_childObj.getTypeName()
            .equalsIgnoreCase("sp23_system"))) {
         // DfLogger.info("tracing", "OBJECT NOT TEMPLATE: " +
         // m_childObj.getObjectName(), null, null);
         // set permissions on all VD components based on WF activity
         if ((m_TaskName.equalsIgnoreCase("Check_Initial_Data"))
           || (m_TaskName
             .equalsIgnoreCase("DemoteToDocDevelopment"))) {
          // DfLogger.info("tracing",
          //"set permissions to content developer: ", null,null);
          // set permissions to content developer if needed
          // aclContDev = dm_450038b280000901_80000500 in devtest
          // repository
          if (m_childObj.getACLName() != "aclContDev") {
           m_childObj
             .setACLName("aclContDev");
           m_childObj.setACLDomain(m_domain);
           m_childObj.save();
          }
         } else if (m_TaskName.equalsIgnoreCase("PromoteToPVAL")) {
          // set permissions to content manager if needed
          // aclContMngr = dm_450038b280000902_80000500 in devtest
          // repository
          if (m_childObj.getACLName() != "aclContMngr") {
           m_childObj
             .setACLName("aclContMngr");
           m_childObj.setACLDomain(m_domain);
           m_childObj.save();
          }
         } else {
          // DfLogger.info("tracing","setChildProperties:TASK: " +
          // m_TaskName,null,null);
         }

         // Process IETM content objects
         if (m_childObj.getPolicyName().equalsIgnoreCase(
           "MRU_development")) {
          if (m_childObj.getCurrentStateName().equalsIgnoreCase("Doc_Development")
            && m_TaskName.equalsIgnoreCase("PromoteToPeerReview")) {
           // Lifecycle state
           // Doc Development => Peer Review
           m_childObj.promote("PEER_REVIEW", lifeCycleOverride, lifeCycleTestOnly);
           m_childObj.save();
           // DfLogger.info("tracing",
           // "DocDevelopment --> Peer_Review: " +
           // m_childObj.getObjectName(),null,null);
          }
          // The workflow templates allow reject/demote when an
          // object meets lifecycle states =
          // PVAL, PMO, Verification, or External_Review for the
          // procedural workflow.
          // Less PVAL, Verification, and External_Review for
          // descriptive workflow.
          else if (m_TaskName.equalsIgnoreCase("DemoteToDocDevelopment")) {
          
          } else if (m_childObj.getCurrentStateName()
            .equalsIgnoreCase("PEER_REVIEW")
            && (m_TaskName.equalsIgnoreCase("PromoteToPVAL"))) {
           // Peer Review to PVAL
           // lifeCycleState = "PVAL";
           m_childObj.promote("PVAL", lifeCycleOverride,
             lifeCycleTestOnly);
           m_childObj.save();
          } else if (m_childObj.getCurrentStateName()
            .equalsIgnoreCase("PEER_REVIEW")
            && (m_TaskName.equalsIgnoreCase("PromoteToPMO"))) {
           // Descriptive Path, will skip over PVAL and go to
           //PMO as it's supposed to do
           // PEER_REVIEW --> PMO
           // lifeCycleState = PMO;
           m_childObj.promote("PMO", lifeCycleOverride,
             lifeCycleTestOnly);
           m_childObj.save();
          } else if (m_childObj.getCurrentStateName()
            .equalsIgnoreCase("PVAL")
            && (m_TaskName.equalsIgnoreCase("PromoteToPMO"))) {
           // PVAL --> PMO
           // lifeCycleState = PMO;
           m_childObj.promote("PMO", lifeCycleOverride,
             lifeCycleTestOnly);
           m_childObj.save();
          } else if (m_childObj.getCurrentStateName()
            .equalsIgnoreCase("PMO")
            && (m_TaskName.equalsIgnoreCase("PromoteToVerification"))) {
           // PMO => Verification
           // lifeCycleState = Verification
           m_childObj.promote("VERIFICATION", lifeCycleOverride, lifeCycleTestOnly);
           m_childObj.save();
          } else if (m_childObj.getCurrentStateName()
            .equalsIgnoreCase("PMO")
            && (m_TaskName.equalsIgnoreCase("PromoteToPA"))) {
           // Descriptive Path, will skip over Verification and External Review
           // and go to PA as it's supposed to do
           // PEER_REVIEW --> PA
           // lifeCycleState = PA
           m_childObj.promote("PA", lifeCycleOverride, lifeCycleTestOnly);
           m_childObj.save();
          } else if (m_childObj.getCurrentStateName()
            .equalsIgnoreCase("Verification")
            && (m_TaskName.equalsIgnoreCase("PromoteToExternalReview"))) {
           // Verification => External
           m_childObj.promote("EXTERNAL_REVIEW",
             lifeCycleOverride, lifeCycleTestOnly);
           m_childObj.save();
          } else if (m_childObj.getCurrentStateName()
            .equalsIgnoreCase("External_Review")
            && (m_TaskName.equalsIgnoreCase("PromoteToPA"))) {
           // External => PA
           m_childObj.promote("PA", lifeCycleOverride, lifeCycleTestOnly);
           m_childObj.save();
          }
          else if (m_childObj.getCurrentStateName()
            .equalsIgnoreCase("PA")
            && (m_TaskName.equalsIgnoreCase("PromoteToDevComplete"))) {
           // External => PA
           m_childObj.promote("DEVELOPMENT_COMPLETE", lifeCycleOverride, lifeCycleTestOnly);
           m_childObj.mark("DEVELOPMENT_COMPLETE");
           m_childObj.save();
           DfLogger.info("tracing", "setChildProperties:new state = DEVELOPMENT_COMPLETE: "
               + m_childObj.getObjectName(), null, null);
          }
          // SHOULD NEVER PROCESS FROM THIS STATE
          else if (m_childObj.getCurrentStateName()
            .equalsIgnoreCase("DEVELOPMENT_COMPLETE"))
           // "DEVELOPMENT COMPLETE" )
          {
           DfLogger.info("tracing",
             "setChildProperties:Object already DEVELOPMENT_COMPLETE: "
               + m_childObj.getObjectName(), null,
             null);
          } else // just log that this object is not processed
          {
           // String LogMsg = "\nChild object " +
           // m_childObj.getObjectName()
           // +
           // " does not meet the lifecycle state for activity!"
           // + m_TaskName;
           // DfLogger.info("tracing",LogMsg ,null,null);
          }
         } // if not a template, set object attributes
        } // lifecycle correct?

        // recurse through children of current child node
        if (childNode.isVirtualDocument()) {
         // DfLogger.info("tracing",
         // "setChildProperties: Process Next Component: "
         // +
         // childNode.getProperties().getString("object_name"),null,
         // null);
         // Recurse through document
         setChildProperties(childNode, null, session, ostream);
        } else // not a virtual document node
        {
         String DbgMsg = childNode.getProperties().getString(
           "object_name")
           + " IS LEAF NODE!";
         DfLogger.info("tracing", DbgMsg, null, null);
        }
       } // for each child node
      } // try
      catch (Exception e) {
       if (e instanceof DfException) {
        String exceptionTrace = ((DfException) e)
          .getStackTraceAsString();
        DfLogger.info("tracing", exceptionTrace, null, null);
        ostream.write(exceptionTrace.getBytes());
       } else {
        DfLogger.info("tracing", e.getMessage(), null, null);
        e.printStackTrace();
       }
      } // catch
    }// setChildProperties
    } // class

    and this is the error I'm getting on the Content Server when I run the

    startMethodServer.sh and leave it running...after it runs completely and I get the message that says it's started, I try to start a workflow, here is the message that shows up on the Content Server...

    Java class must implement IDmMethod interface or have a main() method.

    As you can clearly see from above my class does implement IDmMethod...any ideas?

    Message was edited by: Joe_Chorba

  • bacham2
    bacham2 Member
    edited August 29, 2012 #10

    Where do you get that error? In the main docbase log?

    Also, I'm not sure it matters for this problem but make sure that the a_special_app attribute is set to 'Workflow'.

  • Joe_Chorba
    Joe_Chorba Member
    edited August 29, 2012 #11

    No, I got this error from the startMethodServer.sh script that is run from the Content Server. When you start this script it doesn't close, and when I start a workflow this error pops up and continues to popup. It's on a loop.

  • Joe_Chorba
    Joe_Chorba Member
    edited August 29, 2012 #12

    @bacham2 - yes the a_special_app is selected to Workflow. I created this in composer which gives you a boolean checkbox as to whether it should or should not be Workflow.

    Any other helpful hints?

  • Joe_Chorba
    Joe_Chorba Member
    edited August 29, 2012 #13

    I contacted EMC Support for help and here is what I received from them. Once I try this and see if it works I'll let you all know how it went.

    To summarize here is action plan since you don’t have license to PE which handles workflow method.

    1). Revert change on your  dm_method to use standard doMethod by blanking out the a_special_app attribute. This attribute should not be set to ‘workflow’ if you don’t have PE server side installed.

    2). Then repackage your classes into a jar and place inside:

    $DOCUMENTUM_SHARED/jboss5.1.0/server/DctmServer_MethodServer/deploy/ServerApps.ear/DmMethods.war/WEB-INF/lib/

    Please check to make sure your com.gdais.custom.Workflow folder structure don’t exists anywhere else, if they do, please delete the com/ folder structure. You should not be placing class file inside dba/java_method folder anymore as it’s deprecated.