Fighting with Composer

More than eight years ago EMC released the first version of “very promising” application for packaging and deploying Documentum artifacts – Documentum Composer, intended to kill Documentum Application Builder/Installer. Unfortunately, even after eight years this “promising application” is suitable neither for development nor for installation routines. Really, if you try find some early descriptions of Documentum Composer, for example: Introduction to Documentum Composer, – you will find that nothing has been changed since 6.0SP1 version, EMC bumps version numbers, but Composer still not able to do elementary things, for example, when I try to remove artifact from project I get a weird warning:

What the fuck is “other artifacts”, how can I find them? Open my preferred filemanager and try to find them manually? What a shame! How can I manually modify xml files? Edit via text editor (yeah, some folks think that if application uses XML to store data this means that application uses open format)? Bullshit! How can I edit this:

? It seems that EMC coders has never heard before about UTF-8 encoding and CDATA section in XML! Installation process is tedious as well, interesting, has anybody at EMC heard about java.io.tmpdir system property

or about file names in ZIP specification:

? I believe the answer is “no”. Ultimately, due to a lot of glitches in this “promising application” all experienced Documentum developers try to minimize the amount of interactions with Documentum Composer, the usage pattern varies from one developer to another, the most common patters are:

  • don’t use composer at all – developers write a set of API/DQL/dmbasic scripts and store them in VCS, this approach is extremely straightforward, but it typically requires two kinds sets: one for clean installation and another one for upgrading between application versions
  • use composer to transfer application between environments – developers perform changes in DEV environment using API/DQL/dmbasic scripts, after that they import Documentum artifacts into Composer

I prefer the second option because it is too boring to support two sets of scripts. But this approach has a couple of disadvantages:

  • I need to properly setup composer workspace on CI side, i.e. I need to unpack composer distribution, create empty workspace, create empty dummy project to force composer to create “DocumentumCoreProject” (yeah, Composer does not create DocumentumCoreProject automatically when you try to import project into empty workspace) and delete dummy project, after that the build scenario may look like (extremely error-prone!):
    • Delete composer project from workspace
    • Copy composer project from VCS to workspace
    • Register (import) composer project in workspace
    • Perform some updates in project (like replacing jar files)
    • Build project (or workspace)
  • Sometimes, depending on a target environment, it is required to set upgrade option (i.e. ignore, version or override) for certain artifacts – “manually” editing and committing default.dardef file is not an option

There is an interesting fact related to the first problem: composer does allow to import “external” projects into workspace:

but corresponding “emc.importProject” ant task does not – it requires project to be copied into workspace:

In order to resolve both problems mentioned above I developed a simple eclipse plugin, and now my ant scenario looks like:

<?xml version="1.0"?>
<project name="composer" default="all">

  <property file="${basedir}/src/main/resources/build.properties"/>

  <taskdef name="ap.importProject" classname="tel.panfilov.documentum.composer.ImportProjectAntTask"/>
  <taskdef name="ap.setUpgradeOption" classname="tel.panfilov.documentum.composer.SetUpgradeOptionAntTask"/>

  <target name="create-workspace" description="Create composer workspace">
    <ap.importProject project="<project name>" location="${composer.project.dir}"/>
    <ap.setUpgradeOption project="<project name>">
       <upgradeOptions>
          <artifact name="*" category="com.emc.ide.artifact.bpm.processContainer" value="IGNORE"/>
          <artifact name="wt_executing" category="com.emc.ide.artifact.bpm.processContainer" value="VERSION"/>
       </upgradeOptions>
    </ap.setUpgradeOption>
  </target>

  <target name="build-workspace" description="build eclipse project">
    <eclipse.incrementalBuild kind="full"/>
  </target>

  <target name="clean-workspace" description="clean eclipse project">
    <eclipse.incrementalBuild kind="clean"/>
  </target>

  <target name="all" depends="create-workspace, clean-workspace, build-workspace"/>

</project>

4 thoughts on “Fighting with Composer

  1. I’ve always though of composer as:
    1. EMC employee is fed up with builder. Starts developing an integrated environment on his own.
    2. When project is mature enough EMC decides to use it as replacement for AB
    3. Employee leaves EMC, EMC just “patches” existing composer to work with newer DCTM versions (Which eclipse release is based on? helios?)

    However, for me one of the biggest annoyances is the lack of a mechanism to check the consistency between imported artifacts and actual objects in repository. Having aspects available they could have implemented some kind of timestamp aspect to be checked when installing an artifact so you could be warned if the artifact you’re installing is older than the one being replaced…

    Like

  2. I think that the word “mature” is not applicable here, anyway, if you think that composer is not under development anymore how can you explain EMC’s engagement on eclipse? xCP Designer is based on eclipse too, though wise companies have switched to intellij: http://developer.android.com/sdk/index.html

    However, for me one of the biggest annoyances is the lack of a mechanism to check the consistency between imported artifacts and actual objects in repository.

    I have seen how such option is implemented in xCP Designer – it is better to do such things manually, for example, about 5 years ago I used sql generators to extract artifacts from repository, something like:

    set heading off
    set linesize 4000
    set pagesize 0
    set trimspool on
    spool 05_acls.api
    WITH acl_s AS (SELECT                                       /*+ materialize */
                         r_object_id, object_name, description
                     FROM   dm_acl_sp
                    WHERE   object_name <> 'dm_' || r_object_id)
    SELECT      '-- '
             || TO_CHAR (ROWNUM, '09')
             || '_'
             || object_name
             || CHR (10)
             || stmt
      FROM   (  SELECT   acl_s.object_name,           /*+ use_nl (acl_s, acl_r) */
                            'create,c,dm_acl'
                         || CHR (10)
                         || 'set,c,l,object_name'
                         || CHR (10)
                         || acl_s.object_name
                         || CHR (10)
                         || 'set,c,l,description'
                         || CHR (10)
                         || acl_s.description
                         || CHR (10)
                         || 'set,c,l,owner_name'
                         || CHR (10)
                         || 'dm_dbo'
                         || CHR (10)
                         || concat_all(concat_expr (
                                             'grant,c,l,'
                                          || acl_r.r_accessor_name
                                          || ','
                                          || acl_r.r_accessor_permit
                                          || CASE
                                                WHEN BITAND (
                                                        acl_r.r_accessor_xpermit,
                                                        1
                                                     ) = 0
                                                THEN
                                                   ',execute_proc'
                                             END
                                          || CASE
                                                WHEN BITAND (
                                                        acl_r.r_accessor_xpermit,
                                                        2
                                                     ) = 0
                                                THEN
                                                   ',change_location'
                                             END
                                          || CASE
                                                WHEN BITAND (
                                                        acl_r.r_accessor_xpermit,
                                                        65536
                                                     ) <> 0
                                                THEN
                                                   ',change_state'
                                             END
                                          || CASE
                                                WHEN BITAND (
                                                        acl_r.r_accessor_xpermit,
                                                        131072
                                                     ) <> 0
                                                THEN
                                                   ',change_permit'
                                             END
                                          || CASE
                                                WHEN BITAND (
                                                        acl_r.r_accessor_xpermit,
                                                        262144
                                                     ) <> 0
                                                THEN
                                                   ',change_owner'
                                             END
                                          || CASE
                                                WHEN BITAND (
                                                        acl_r.r_accessor_xpermit,
                                                        524288
                                                     ) <> 0
                                                THEN
                                                   ',delete_object'
                                             END,
                                          CHR (10)
                                       ))
                         || CHR (10)
                         || 'save,c,l'
                         || CHR (10)
                            stmt
                  FROM   dm_acl_rp acl_r, acl_s
                 WHERE   acl_r.r_object_id = acl_s.r_object_id
              GROUP BY   acl_s.object_name, acl_s.description, acl_s.r_object_id
              ORDER BY   acl_s.r_object_id ASC);
    spool off
    
    set heading off
    set linesize 4000
    set pagesize 0
    set trimspool on
    spool 04_relation_types.dql
    SELECT      '-- '
             || TO_CHAR (ROWNUM, '09')
             || '_'
             || relation_name
             || CHR (10)
             || stmt
      FROM   (  SELECT   relation_name,
                            'create dm_relation_type object'
                         || CHR (10)
                         || 'set relation_name='''
                         || relation_name
                         || ''''
                         || CHR (10)
                         || 'set security_type='''
                         || security_type
                         || ''''
                         || CHR (10)
                         || 'set parent_type='''
                         || parent_type
                         || ''''
                         || CHR (10)
                         || 'set child_type='''
                         || child_type
                         || ''''
                         || CHR (10)
                         || 'set description='''
                         || description
                         || ''''
                         || CHR (10)
                         || 'set direction_kind='
                         || direction_kind
                         || CHR (10)
                         || 'set integrity_kind='
                         || integrity_kind
                         || CHR (10)
                         || 'set permanent_link='
                         || permanent_link
                         || CHR (10)
                         || 'set copy_child='
                         || copy_child
                         || CHR (10)
                         || 'go'
                            stmt
                  FROM   dm_relation_type_sp
                  where relation_name not like 'DM_fk%'
              ORDER BY   r_object_id);
    spool off
    

    Like

  3. I forgot to quote “mature” in that sentece, I meant “kind of working most of the time” :P.

    About the eclipse/intellij I couldn’t care less about the underlying IDE they use (even if it were netbeans), it is just a matter of personal preferences (and business requirements sometimes, ie: eclipse has a wider plugin ecosystem than intellij so some products only integrate with eclipse).

    Like

  4. If compare IDEs, IntelliJ has a set of killer features like FernFlower decompiler, upsource integration (if you take a look at upsource roadmap you will find that they are going to kill gitlab and bitbucket :)), which make IntelliJ the only Java IDE. Point about “plugin ecosystem” is bit weird: you need to install a dozen of plugins into Jenkins to make it work or just install TeamCity, the same is about Jira vs YouTrack and Eclipse vs IntelliJ.

    But my point was another: if EMC got a bad experience with composer (which is based on eclipse) what is the point to start developing new RAD tool based on eclipse too?

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s