Q & A. IX

Hi,

i’m relatively new to the xCP2 (and documentum) world and i have a question: the color of the application’s background is blue and i don’t like blue… juste joking !

i couldn’t find anywhere tips about continuous integration. is there a way to build and xCP2 project with commande line ? i want to make a continuous integration using Jenkins, SOMETHING to build, and (i think)the xmstool to deploy it every night.
However, couldn’t find anything to build the project from command line(and i shearshed up to google page 5!) in a unix environnement. Do you have any clues about what i can use?

Thanks,
Regards,
Rochdi

Hi,

I’m not sure that I’ll able to answer your question because I have never tried to perform automatic builds of xCP2 projects before (actually, after some unsuccessful attempts to create a complex (not a “hello world”) xCP2 application we have found that at current moment xCP2 is completely unusable/unstable/unreliable/undocumented and switched back to WDK/DFC), however EMC folks tell that there is an option to mavenize xCP2 project – it seems that attempt to execute “mvm package” is doomed to failure if xCP Designer is up and running:

> G:\app\maven\3.2.3\bin\mvn package -Dmaven.repo.local=G:\app\xCPDesigner\maven

....

[ERROR] Unexpected system error packaging dar for project 'ap'
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.120 s
[INFO] Finished at: 2015-07-30T21:34:08+10:00
[INFO] Final Memory: 18M/223M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal com.emc.xcp.builder:xcp-dar:1.0.8:run (xcp-dar) on project ap: 
   Xcp mojo executing command 'preparepackage' for project 'ap' failed unexpectedly: j
ava.lang.IllegalArgumentException: xcpProject must not be null.
[ERROR] at com.emc.xcp.builder.packaging.PackagerUtil.generateRunConfig(PackagerUtil.java:18)
[ERROR] at internal.com.emc.xcp.builder.packaging.projectpackagers.RunConfigPackager.doPackaging(RunConfigPackager.java:14)
[ERROR] at internal.com.emc.xcp.builder.packaging.InternalPackagerUtil.packageProject(InternalPackagerUtil.java:22)
[ERROR] at internal.com.emc.xcp.builder.packaging.maven.XcpDarCommand.execute(XcpDarCommand.java:43)
[ERROR] at internal.com.emc.xcp.builder.build.maven.MavenHookManager.execute(MavenHookManager.java:29)
[ERROR] at internal.com.emc.xcp.builder.build.maven.MavenHookServlet.doPost(MavenHookServlet.java:51)
[ERROR] at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
[ERROR] at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
[ERROR] at org.eclipse.equinox.http.registry.internal.ServletManager$ServletWrapper.service(ServletManager.java:180)
[ERROR] at org.eclipse.equinox.http.servlet.internal.ServletRegistration.service(ServletRegistration.java:61)
[ERROR] at org.eclipse.equinox.http.servlet.internal.ProxyServlet.processAlias(ProxyServlet.java:128)
[ERROR] at org.eclipse.equinox.http.servlet.internal.ProxyServlet.service(ProxyServlet.java:68)
[ERROR] at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
[ERROR] at org.eclipse.equinox.http.jetty.internal.HttpServerManager$InternalHttpServiceServlet.service(HttpServerManager.java:384)
[ERROR] at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:598)
[ERROR] at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:486)

but in offline mode it does build something (note designerPath property):

G:\app\maven\3.2.3\bin\mvn package -Dmaven.repo.local=G:\app\xCPDesigner\maven -DdesignerPath=G:\app\xCPDesigner

...

[INFO] Webapp assembled in [5613 msecs]
[INFO] Building war: G:\app\xCPDesigner\Applications\ap\ap\target\ap-ap-1.0.0.war
[WARNING] Warning: selected war files include a WEB-INF/web.xml which will be ignored
(webxml attribute is missing from war task, or ignoreWebxml attribute is specified as 'true')
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:02 min
[INFO] Finished at: 2015-07-30T21:36:41+10:00
[INFO] Final Memory: 15M/218M
[INFO] ------------------------------------------------------------------------

Q & A. IV

This guy asked me through linkedin.

I saw you in EMC community and wanted your advice on xCP 2.2 workflows. We have xCP 1.6 workflows and currently planning to re-design them to xCP 2.2 and having below queries ..

1) We have a custom document object type called cus_enterpirse which inherits from dm_document. We are using this type as package in current xCP 1.6 workflow. Can we use the same object type in xCP 2.2 environment (like adopting cus_enterprise ) for workflows ?

2) Will there be any conflicts/issues for existing workflows in xCP 1.6 environment if we adopt the custom type in xCP designer and install the application using xCP 2.2 environment ? Also we wanted to run both xCP 1.6 and xCP 2.2 workflows parallelly for same data model as packages, Will this have any impact

3) We heard that we cannot use the same data model in xCP 1.6 and xCP 2.2 environment and we need to create new data model for workflows and then use it in xCP 2.2 workflows. Is that correct?

Sukumar, first of all, you seem to be a very good EMC customer – once you already bought a stillborn product (xCP), now you are taking a part in beta-testing (xCP2), and in my opinion EMC support must make every effort to help you in your project 🙂

Anyway, type adoption feature does work (we were able to make xCP2 work with composer types and webtop work with xCP2 workflows) but there are some glitches you would like to know:

  • xCP Designer behaves very strange with adopted types: removing adopted type from project and further installing this project causes removing adopted type from repository – be careful with this “feature” (yeap, EMC considers this bug as feature request)
  • interoperability between xCP2 and other applications, which was promised by EMC in xCP2.1, was nothing but fail:
  • Yes, xCP2 workflows use another model (no aliassets, no custom methods, process variables are stored differently), technically this means that you should either dot not work with workflows through old application (for example, xCP2 does display tasks only for it’s workflows) or implement custom adapter, for example below is our utility class that allows to work with different models of process variables (it assumes that there is some naming convention for process variables):
    /**
     * @author Andrey B. Panfilov <andrew@panfilov.tel>
     */
    public class ProcessVariableUtils {
    
        public ProcessVariableUtils() {
            super();
        }
    
        public static Object getValue(IDfWorkitemEx workitem, String variableName)
            throws DfException {
            int dotIndex = variableName.indexOf(".");
            if (dotIndex < 0) {
                return getProcessVariableValueInternal(workitem, variableName);
            }
            for (String candidate : structuredToPrimitive(variableName)) {
                try {
                    return getProcessVariableValueInternal(workitem, candidate);
                } catch (ProcessVariableNotFoundException ex) {
                    // pass
                } catch (ProcessVariableTypeNullIdException ex) {
                    // pass
                }
            }
            String setting = variableName.substring(0, dotIndex);
            String parameter = variableName.substring(dotIndex + 1,
                    variableName.length());
            return workitem.getStructuredDataTypeAttrValue(setting, parameter);
        }
    
        private static Object getProcessVariableValueInternal(
                IDfWorkitemEx workitem, String variableName) throws DfException {
            return getNonProxied(workitem).getPrimitiveVariableValue(variableName);
        }
    
        public static Object getValue(IDfWorkflowEx workflow, String variableName)
            throws DfException {
            int dotIndex = variableName.indexOf(".");
            if (dotIndex < 0) {
                return getProcessVariableValueInternal(workflow, variableName);
            }
            for (String candidate : structuredToPrimitive(variableName)) {
                try {
                    return getProcessVariableValueInternal(workflow, candidate);
                } catch (ProcessVariableNotFoundException ex) {
                    // pass
                } catch (ProcessVariableTypeNullIdException ex) {
                    // pass
                }
            }
            String setting = variableName.substring(0, dotIndex);
            String parameter = variableName.substring(dotIndex + 1,
                    variableName.length());
            return workflow.getStructuredDataTypeAttrValue(setting, parameter);
        }
    
        private static Object getProcessVariableValueInternal(
                IDfWorkflowEx workflow, String variableName) throws DfException {
            return getNonProxied(workflow).getPrimitiveVariableValue(variableName);
        }
    
        public static void setValue(IDfWorkitemEx workitem, String variableName,
                Object value) throws DfException {
            int dotIndex = variableName.indexOf(".");
            if (dotIndex < 0) {
                setProcessVariableValueInternal(workitem, variableName, value);
                return;
            }
            for (String candidate : structuredToPrimitive(variableName)) {
                try {
                    setProcessVariableValueInternal(workitem, candidate, value);
                    return;
                } catch (ProcessVariableNotFoundException ex) {
                    // pass
                } catch (ProcessVariableTypeNullIdException ex) {
                    // pass
                }
            }
            String setting = variableName.substring(0, dotIndex);
            String parameter = variableName.substring(dotIndex + 1,
                    variableName.length());
            workitem.setStructuredDataTypeAttrValue(setting, parameter, value);
        }
    
        private static void setProcessVariableValueInternal(IDfWorkitemEx workitem,
                String variableName, Object value) throws DfException {
            getNonProxied(workitem).setPrimitiveObjectValue(variableName, value);
        }
    
        public static void setValue(IDfWorkflowEx workflow, String variableName,
                Object value) throws DfException {
            int dotIndex = variableName.indexOf(".");
            if (dotIndex < 0) {
                setProcessVariableValueInternal(workflow, variableName, value);
                return;
            }
            for (String candidate : structuredToPrimitive(variableName)) {
                try {
                    setProcessVariableValueInternal(workflow, candidate, value);
                    return;
                } catch (ProcessVariableNotFoundException ex) {
                    // pass
                } catch (ProcessVariableTypeNullIdException ex) {
                    // pass
                }
            }
            String setting = variableName.substring(0, dotIndex);
            String parameter = variableName.substring(dotIndex + 1,
                    variableName.length());
            workflow.setStructuredDataTypeAttrValue(setting, parameter, value);
        }
    
        private static void setProcessVariableValueInternal(IDfWorkflowEx workflow,
                String variableName, Object value) throws DfException {
            getNonProxied(workflow).setPrimitiveObjectValue(variableName, value);
        }
    
        public static Object[] getValues(IDfWorkitemEx workitem, String variableName)
            throws DfException {
            int dotIndex = variableName.indexOf(".");
            if (dotIndex < 0) {
                return getProcessVariableValuesInternal(workitem, variableName);
            }
            for (String candidate : structuredToPrimitive(variableName)) {
                try {
                    return getProcessVariableValuesInternal(workitem, candidate);
                } catch (ProcessVariableNotFoundException ex) {
                    // pass
                } catch (ProcessVariableTypeNullIdException ex) {
                    // pass
                }
            }
            String setting = variableName.substring(0, dotIndex);
            String parameter = variableName.substring(dotIndex + 1,
                    variableName.length());
            return workitem.getStructuredDataTypeAttrValues(setting, parameter);
        }
    
        private static Object[] getProcessVariableValuesInternal(
                IDfWorkitemEx workitem, String variableName) throws DfException {
            try {
                workitem = getNonProxied(workitem);
                Method method = ReflectionUtils.getMethod(workitem.getClass(),
                        "getRepeatingPrimitiveVariableValues", String.class);
                if (method != null) {
                    List result = (List) method.invoke(workitem, variableName);
                    if (result == null) {
                        return new Object[] {};
                    }
                    return result.toArray(new Object[result.size()]);
                }
                throw new ProcessVariableNotFoundException(
                        "getRepeatingPrimitiveVariableValues", variableName);
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable t = ex.getTargetException();
                if (t instanceof DfException) {
                    throw (DfException) t;
                }
                throw new RuntimeException(ex);
            }
        }
    
        public static Object[] getValues(IDfWorkflowEx workflow, String variableName)
            throws DfException {
            int dotIndex = variableName.indexOf(".");
            if (dotIndex < 0) {
                return getProcessVariableValuesInternal(workflow, variableName);
            }
            for (String candidate : structuredToPrimitive(variableName)) {
                try {
                    return getProcessVariableValuesInternal(workflow, candidate);
                } catch (ProcessVariableNotFoundException ex) {
                    // pass
                } catch (ProcessVariableTypeNullIdException ex) {
                    // pass
                }
            }
            String setting = variableName.substring(0, dotIndex);
            String parameter = variableName.substring(dotIndex + 1,
                    variableName.length());
            return workflow.getStructuredDataTypeAttrValues(setting, parameter);
        }
    
        private static Object[] getProcessVariableValuesInternal(
                IDfWorkflowEx workflow, String variableName) throws DfException {
            try {
                workflow = getNonProxied(workflow);
                Method method = ReflectionUtils.getMethod(workflow.getClass(),
                        "getRepeatingPrimitiveVariableValues", String.class);
                if (method != null) {
                    List result = (List) method.invoke(workflow, variableName);
                    if (result == null) {
                        return new Object[] {};
                    }
                    return result.toArray(new Object[result.size()]);
                }
                throw new ProcessVariableNotFoundException(
                        "getRepeatingPrimitiveVariableValues", variableName);
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable t = ex.getTargetException();
                if (t instanceof DfException) {
                    throw (DfException) t;
                }
                throw new RuntimeException(ex);
            }
        }
    
        public static void setValues(IDfWorkitemEx workitem, String variableName,
                Object[] values) throws DfException {
            int dotIndex = variableName.indexOf(".");
            if (dotIndex < 0) {
                setProcessVariableValuesInternal(workitem, variableName, values);
                return;
            }
            for (String candidate : structuredToPrimitive(variableName)) {
                try {
                    setProcessVariableValuesInternal(workitem, candidate, values);
                    return;
                } catch (ProcessVariableNotFoundException ex) {
                    // pass
                } catch (ProcessVariableTypeNullIdException ex) {
                    // pass
                }
            }
            String setting = variableName.substring(0, dotIndex);
            String parameter = variableName.substring(dotIndex + 1,
                    variableName.length());
            workitem.setStructuredDataTypeAttrValues(setting, parameter, values);
        }
    
        private static void setProcessVariableValuesInternal(
                IDfWorkitemEx workitem, String variableName, Object[] values)
            throws DfException {
            try {
                workitem = getNonProxied(workitem);
                Method method = ReflectionUtils.getMethod(workitem.getClass(),
                        "setRepeatingPrimitiveObjectValues", String.class,
                        List.class);
                if (method != null) {
                    method.invoke(workitem, variableName, Arrays.asList(values));
                    return;
                }
                throw new ProcessVariableNotFoundException(
                        "setRepeatingPrimitiveObjectValues", variableName);
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable t = ex.getTargetException();
                if (t instanceof DfException) {
                    throw (DfException) t;
                }
                throw new RuntimeException(ex);
            }
        }
    
        public static void setValues(IDfWorkflowEx workflow, String variableName,
                Object[] values) throws DfException {
            int dotIndex = variableName.indexOf(".");
            if (dotIndex < 0) {
                setProcessVariableValuesInternal(workflow, variableName, values);
                return;
            }
            for (String candidate : structuredToPrimitive(variableName)) {
                try {
                    setProcessVariableValuesInternal(workflow, candidate, values);
                    return;
                } catch (ProcessVariableNotFoundException ex) {
                    // pass
                } catch (ProcessVariableTypeNullIdException ex) {
                    // pass
                }
            }
            String setting = variableName.substring(0, dotIndex);
            String parameter = variableName.substring(dotIndex + 1,
                    variableName.length());
            workflow.setStructuredDataTypeAttrValues(setting, parameter, values);
        }
    
        private static void setProcessVariableValuesInternal(
                IDfWorkflowEx workflow, String variableName, Object[] values)
            throws DfException {
            try {
                workflow = getNonProxied(workflow);
                Method method = ReflectionUtils.getMethod(workflow.getClass(),
                        "setRepeatingPrimitiveObjectValues", String.class,
                        List.class);
                if (method != null) {
                    method.invoke(workflow, variableName, Arrays.asList(values));
                    return;
                }
                throw new ProcessVariableNotFoundException(
                        "setRepeatingPrimitiveObjectValues", variableName);
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable t = ex.getTargetException();
                if (t instanceof DfException) {
                    throw (DfException) t;
                }
                throw new RuntimeException(ex);
            }
        }
    
        private static List<String> structuredToPrimitive(String variableName) {
            List<String> candidates = new ArrayList<String>(2);
            candidates.add(variableName.replace('.', '_').replace('/', '_'));
            candidates.add(variableName.replace('.', '_').replace('/', '_')
                    .toLowerCase());
            return candidates;
        }
    
        private static IDfWorkitemEx getNonProxied(IDfWorkitemEx workitemEx) {
            if (workitemEx instanceof IDfWorkitemExWrapper) {
                workitemEx = (IDfWorkitemEx) ((IDfWorkitemExWrapper) workitemEx)
                        .getWrappedObject();
            }
            if (workitemEx instanceof IProxyHandler) {
                return (IDfWorkitemEx) ((IProxyHandler) workitemEx)
                        .____getImp____();
            }
            return workitemEx;
        }
    
        private static IDfWorkflowEx getNonProxied(IDfWorkflowEx workflowEx) {
            if (workflowEx instanceof IProxyHandler) {
                return (IDfWorkflowEx) ((IProxyHandler) workflowEx)
                        .____getImp____();
            }
            return workflowEx;
        }
    
    }
    
    

XCP2 vs ACLs

Yesterday another my skypemate asked me whether I know something about following XCP error:

An error occurred while performing the requested operation. Please try again.

  Details 
    Error in operation Object create failure type=jorm1_nomupis

Error code: E_ECM_OPERATION_ERROR
[DM_SYSOBJECT_E_INVALID_ACL_DOMAIN]error: 
    "The <object_type> '<object_name>' is given an invalid ACL domain 'dmadmin'."

EMC published ridiculous solution for this error, fortunately I did know the root cause of this error. Three cases:

user’s ACL:

API> retrieve,c,dm_acl where owner_name=USER
...
4501fd088003ad00
API> get,c,l,object_name
...
dm_4501fd088003ad00
API> create,c,dm_document
...
0901fd0880792c3e
API> set,c,l,acl_name
SET> dm_4501fd088003ad00
...
OK
API> set,c,l,acl_domain
SET> test01
...
OK
API> save,c,l
...
OK

repository owner’s ACL:

API> retrieve,c,dm_acl where owner_name='ssc_dev'
...
4501fd088002ec25
API> get,c,l,object_name
...
sample_acl
API> create,c,dm_document
...
0901fd0880792c3d
API> set,c,l,acl_name
SET> sample_acl
...
OK
API> set,c,l,acl_domain
SET> dm_dbo
...
OK
API> save,c,l
...
OK

foreign ACL:

API> retrieve,c,dm_acl where owner_name='dmadmin'
...
4501fd088000020a
API> get,c,l,object_name
...
dm_4501fd088000020a
API> create,c,dm_document
...
0901fd0880792c3c
API> set,c,l,acl_name
SET> dm_4501fd088000020a
...
OK
API> set,c,l,acl_domain
SET> dmadmin
...
OK
API> save,c,l
...
[DM_SYSOBJECT_E_INVALID_ACL_DOMAIN]error:  
   "The dm_document '' is given an invalid ACL domain 'dmadmin'."

Documentation (fundamentals guide, bit confusing but previous listing makes it clear):

  • Public ACLs are available for use by any user in the repository. Public ACLs created by the repository owner are called system ACLs. System ACLs can only be managed by the repository owner. Other public ACLs can be managed by their owners or a user with Sysadmin or Superuser
    privileges.
  • Private ACLs are created and owned by a user other than the repository owner. However, unlike public ACLs, private ACLs are available for use only by their owners, and only their owners or a superuser can manage them.

The problem was: by default XCP objects inherit ACLs from target folder:

and somebody decided to grant additional permissions on folder – strange that XCP does not have any foolproof.

Tracking changes in TBO

Initially I wanted to write something like “DFC has a cool method ISession#getUncachedObject(IDfId objectId, String currencyCheckValue) that allows to track changes in TBO”, but after investigating how XCP wrongly implements the same functionality in business events, I realized that it’s worth to pay more attention to the problem, because even vendor does not know how DFC does work.
Continue reading