QC-custom-fieldhandler.pxml

How to write custom field handlers using the QC connector.

Below are the 4 sections relating to this QC connector run:

  1. This configuration file: QC-custom-fieldhandlers.pxml
  2. The Ruby 1st source file: field_handlers/sample_dogs_to_chiens_field_handler.rb
  3. The Ruby 2nd source file: field_handlers/qc_username_to_rally_email_address_field_handler.rb
  4. The logfile output: rallylog.log

NOTE: This example of custom field handlers is for QC connector version 4.3.0 and above. Previous version of the connector required a different type of setup in the source file.

1. Configuration file QC-custom-fieldhandlers.pxml


<Config>
        <RallyConnection>
                <Url>Your-Rally-URL</Url>
                <WorkspaceName>Your-Rally-Workspace</WorkspaceName>
                <Projects>
                        <Project>Your-Rally-Project</Project>
                </Projects>
                <User>Your-Rally-Username</User>
                <Password>Your-Rally-Password</Password>
                <ArtifactType>Defect</ArtifactType>
                <ExternalIDField>Your-Rally-ExternalID</ExternalIDField>
                <CopySelectors>
                        <CopySelector>FormattedID = DE352</CopySelector>
                </CopySelectors>
        </RallyConnection>

        <QCConnection>
            <Url>Your-QC-URL</Url>
            <Domain>Your-QC-Domain</Domain>
            <Project>Your-QC-Project</Project>
            <User>Your-QC-Username</User>
            <Password>Your-QC-Password</Password>
            <ArtifactType>BUG</ArtifactType>
            <IDField>BG_BUG_ID</IDField>
            <ExternalIDField>Your-QC-ExternalID</ExternalIDField>
            <ExternalEndUserIDField>BG_USER_03</ExternalEndUserIDField>
            <CopySelectors>
                <CopySelector>BG_BUG_ID = 86</CopySelector>
            </CopySelectors>
            <FieldDefaults>
                <Field><Name>BG_DETECTION_DATE</Name> <Default>2014-01-01</Default></Field>
                <Field><Name>BG_SEVERITY</Name>       <Default>1-Low</Default></Field>
            </FieldDefaults>
        </QCConnection>

        <Connector>
            <FieldMapping>
                <Field><Rally>Name</Rally>        <Other>BG_SUMMARY</Other></Field>
                <Field><Rally>Description</Rally> <Other>BG_DESCRIPTION</Other></Field>
                <Field><Rally>SubmittedBy</Rally> <Other>BG_DETECTED_BY</Other></Field>
                </FieldMapping>

                <RallyFieldHandlers>
                        <SampleDogsToChiensFieldHandler>
                                <FieldName>Description</FieldName>
                        </SampleDogsToChiensFieldHandler>

                        <RallyUsernameToQcUserFieldHandler>
                                <FieldName>SubmittedBy</FieldName>
                        </RallyUsernameToQcUserFieldHandler>
                </RallyFieldHandlers>
        </Connector>

        <ConnectorRunner>
                <Preview>false</Preview>
                <LogLevel>Debug</LogLevel>
                <Services>COPY_QC_TO_RALLY,  COPY_RALLY_TO_QC</Services>
        </ConnectorRunner>
</Config>

2. The Ruby first source file field_handlers/sample_dogs_to_chiens_field_handler.rb


################################################################################
# File:
#	sample_dogs_to_chiens_field_handler.rb
#
# Author:
#	JPKole 15-Dec-2011
#
# Purpose:
#	This is the Ruby source module which will be invoked by the QC connector
#	in order to transform all strings in the field "Description" in this
#	manner:
#			Rally to QC:  " Rally-Dogs " to " QC-Chiens "
#			QC to Rally:  " QC-Chiens " to " Rally-Dogs "
#
#	For this to work, you need to put the following Ruby code into the file
#	named "sample_dogs_to_chiens_field_handler.rb", within the folder named
#	"field_handlers", which should be within your working folder (i.e. the
#	folder from where you invoke the connector). In my test, the file was
#	here:
#
#	C:\Users\jpkole\field_handlers\sample_dogs_to_chiens_field_handler.rb
#
################################################################################

require 'rallyeif/wrk/field_handlers/field_handler'

module RallyEIF
  module WRK
    module FieldHandlers

      class SampleDogsToChiensFieldHandler < RallyFieldHandler

        #TODO - What other fields could we have here?
        VALID_REFERENCES = [:Description]

        def initialize(field_name = nil)
          super(field_name)
        end

        def transform_out(artifact)
          #artifact is the QC bug
          RallyLogger.debug(self, "transform_out() being invoked.")
          value = @connection.get_value(artifact, @field_name.to_s)
          if !value.nil?
            value.gsub(/ Rally-Dogs /, ' QC-Chiens ')
          else
            value
          end
        end

        def transform_in(value)
          RallyLogger.debug(self, "transform_in() being invoked.")
          if !value.nil?
            value.gsub(/ QC-Chiens /, " Rally-Dogs ") if !value.nil?
          else
            value
          end
        end

        def read_config(fh_element)
          super(fh_element)
          fieldname_element_check(fh_element)
          if (VALID_REFERENCES.index(@field_name) == nil)
            raise UnrecoverableException.new("Field name for SampleDogsToChiensFieldHandler must be from " +
                                                 "the following set #{VALID_REFERENCES}", self)
          end
        end
      end
    end
  end
end


3. The Ruby second source file field_handlers/qc_username_to_rally_email_address_field_handler.rb


# Purpose: To translate Submitter and Owner field strings.
# Filename:  field_handlers/qc_username_to_rally_email_address_field_handler.rb
# For example:	Rally to QC:  "[email protected]" to "jpkole_rallydev.com"
#		QC to Rally:  "jpkole_rallydev.com" to "[email protected]"
#
# Configuration file usage:
#       <Config>
#       ....
#               <Connector>
#                       <FieldMapping>
#                               <Field><Rally>Name</Rally>              <Other>BG_SUMMARY</Other></Field>
#                               <Field><Rally>Description</Rally>       <Other>BG_DESCRIPTION</Other></Field>
#                               <Field><Rally>SubmittedBy</Rally>       <Other>BG_DETECTED_BY</Other></Field>
#                               <Field><Rally>Owner</Rally>             <Other>BG_RESPONSIBLE</Other></Field>
#                       </FieldMapping>
#                       ....
#                       <RallyFieldHandlers>
#                               ....
#                               <RallyUsernameToQcUserFieldHandler>
#                                       <FieldName>SubmittedBy</FieldName>
#                               </RallyUsernameToQcUserFieldHandler>
#
#                               <RallyUsernameToQcUserFieldHandler>
#                                       <FieldName>Owner</FieldName>
#                               </RallyUsernameToQcUserFieldHandler>
#                       </RallyFieldHandlers>
#               </Connector>
#               ...

require 'rallyeif/wrk/field_handlers/field_handler'

module RallyEIF
  module WRK
    module FieldHandlers

      class RallyUsernameToQcUserFieldHandler < RallyFieldHandler

        VALID_REFERENCES = [:Owner, :SubmittedBy]

        def initialize(field_name = nil)
          super(field_name)
        end

        def transform_out(artifact)
          RallyLogger.debug(self, "transform_out() being invoked.")
          value = @connection.get_value(artifact, @field_name.to_s)

          if value.is_a?(RallyAPI::RallyObject)
            # "value" is a "RallyObject" in QC connector versions after 2.8.8
            # puts "DEBUG(RallyUsernameToQcUserFieldHandler.transform_out): value.to_s=#{value.to_s}"
            myusername = value.to_s
          elsif value.is_a? Integer
            # "value" is a "String" in connector 2.8.8 and before
            # puts "DEBUG(RallyUsernameToQcUserFieldHandler.transform_out): value=#{value}"
            myusername = value
          else
            raise UnrecoverableException.new("Unexpected type on 'value' = #{value.class}.")
          end

          if !myusername.nil?
            retval = myusername.split("@").first
          else
            retval = myusername
          end
          return retval
        end

        def transform_in(value)
          # The parameter "value" is a string containing the QC user name
          RallyLogger.debug(self, "transform_in() being invoked.")
          if !value.nil?
            retval = value.dup.concat("@rallydev.com")
          else
            retval = value
          end
          return retval
        end

        def read_config(fh_element)
          super(fh_element)
          fieldname_element_check(fh_element)

          if (VALID_REFERENCES.index(@field_name) == nil)
            raise UnrecoverableException.new("Field name for RallyUsernameToQcUserFieldHandler must be from " +
             "the following set #{VALID_REFERENCES}", self)
          end
        end
      end
    end
  end
end

4. The rallylog.log file for QC-custom-fieldhandlers.pxml


****************************************************************************************
     rally2_qc_connector
         pid: 2184
         starting at: 2014-01-21 21:48:39 Z
         cwd: Z:/JPKoleQC
         configs: x061-85053.xml
         interval: -1
         connector-version: Connector version: 0.1.8-62-master-33b4eb53ac49955bbfc4c51f386aa49462dfdad9
         rally-version: Rally Spoke version 4.0.2 using rally_api gem version 0.9.25
         other-spoke: QCConnection version: 4.3.0-32-master-64631d93c2332fa4a516641afcd78aa79a89b927
****************************************************************************************
  ANY : RallyEIF::WRK::ConnectorRunner.block in run - processing to commence using content from x061-85053.xml
  ANY : Class.read_config_file - x061-85053.xml last modified 2014-01-21 00:02:33 UTC, size: 1939 chars
  ANY : RallyEIF::WRK::RallyConnection.initialize - Initializing Rally connection version 4.0.2
 INFO : RallyEIF::WRK::RallyConnection.initialize - Rally Web Services version 1.42
  ANY : RallyEIF::WRK::QCConnection.initialize - Initializing Quality Center connection version 4.3.0
 INFO : RallyEIF::WRK::Connector.initialize - Ruby platform i386-mingw32
 INFO : RallyEIF::WRK::Connector.initialize - Ruby version 2.0.0
 INFO : RallyEIF::WRK::QCConnection.connect - Connecting to Quality Center at http://vmwin2008qc11.f4tech.com:8080/qcbin as user jpqc11
DEBUG : RallyEIF::WRK::QCConnection.block in identify_qc_version - Preparing to open Registry to examine: Software\Classes\CLSID\{C5CBD7B2-490C-45f5-8C40-B8C3D108E6D7}\InprocServer32
DEBUG : RallyEIF::WRK::QCConnection.block in identify_qc_version - Registry Software\Classes\CLSID\{C5CBD7B2-490C-45f5-8C40-B8C3D108E6D7}\InprocServer32 opened...
DEBUG : RallyEIF::WRK::QCConnection.block (2 levels) in identify_qc_version - Registry path to HPQC OTAClient.dll ==> C:\PROGRA~2\COMMON~1\MERCUR~1\TDAPIC~1\OTACLI~1.DLL
DEBUG : RallyEIF::WRK::QCConnection.win_path_expanded - expanded Registry path to DLL target: C:/Program Files (x86)/Common Files/Mercury Interactive/TDAPIClient/OTAClient.dll
 INFO : RallyEIF::WRK::QCConnection.connect - Connected to Quality Center at http://vmwin2008qc11.f4tech.com:8080/qcbin/wcomsrv.dll (version 11.0.0.8258)
 INFO : RallyEIF::WRK::QCConnection.connect -   Domain: DEFAULT
 INFO : RallyEIF::WRK::QCConnection.connect -   Project: JPproject11
 INFO : RallyEIF::WRK::RallyConnection.connect - Connecting to Rally
DEBUG : RallyEIF::WRK::RallyConnection.connect - In connect begin clause - connecting to Rally via rally_api
DEBUG : RallyEIF::WRK::RallyConnection.connect - Looking up projects
 INFO : RallyEIF::WRK::RallyConnection.connect - Connected to Rally at https://rally1.rallydev.com/slm -  Workspace: JP's Workspace
 INFO : RallyEIF::WRK::RallyConnection.connect -   Projects: PR01
 INFO : RallyEIF::WRK::Connector.validate - Beginning validation
DEBUG : RallyEIF::WRK::RallyConnection.validate - Rally Connection - user entry "[email protected]" detected in config file
DEBUG : RallyEIF::WRK::RallyConnection.validate - Rally Connection - password entry detected in config file
DEBUG : RallyEIF::WRK::RallyConnection.validate - Rally Connection - artifact type "defect" validated
DEBUG : RallyEIF::WRK::RallyConnection.validate - Rally IDField name of "ObjectID" validated
DEBUG : RallyEIF::WRK::RallyConnection.validate - Rally ExternalIDField name of "QCPR01ExtID" validated
DEBUG : RallyEIF::WRK::RallyConnection.validate - Rally Connection - FieldHandler target fields existence validated
DEBUG : RallyEIF::WRK::RallyConnection.validate - Rally Connection - Field Defaults settings validated
DEBUG : RallyEIF::WRK::Connector.validate - RallyConnection validate succeeded
DEBUG : RallyEIF::WRK::QCConnection.validate - Quality Center Connection - user entry "jpqc11" detected in config file
DEBUG : RallyEIF::WRK::QCConnection.validate - Quality Center Connection - password entry detected in config file
DEBUG : RallyEIF::WRK::QCConnection.validate - Quality Center Connection - artifact type "bug" validated
DEBUG : RallyEIF::WRK::QCConnection.validate - Quality Center IDField name of "BG_BUG_ID" validated
DEBUG : RallyEIF::WRK::QCConnection.validate - Quality Center ExternalIDField name of "BG_USER_01" validated
DEBUG : RallyEIF::WRK::QCConnection.validate - Quality Center ExternalEndUserIDField name of "BG_USER_03" validated
DEBUG : RallyEIF::WRK::QCConnection.validate - Quality Center Connection - FieldHandler target fields existence validated
DEBUG : RallyEIF::WRK::QCConnection.validate - Quality Center Connection - Field Defaults settings validated
DEBUG : RallyEIF::WRK::Connector.validate - Quality Center Connection validate succeeded
DEBUG : RallyEIF::WRK::Connector.block in validate - RallyConnection field_mapping target "Name" existence validated
DEBUG : RallyEIF::WRK::Connector.block in validate - Quality Center Connection field_mapping target "BG_SUMMARY" existence validated
DEBUG : RallyEIF::WRK::Connector.block in validate - RallyConnection field_mapping target "Description" existence validated
DEBUG : RallyEIF::WRK::Connector.block in validate - Quality Center Connection field_mapping target "BG_DESCRIPTION" existence validated
DEBUG : RallyEIF::WRK::Connector.block in validate - RallyConnection field_mapping target "SubmittedBy" existence validated
DEBUG : RallyEIF::WRK::Connector.block in validate - Quality Center Connection field_mapping target "BG_DETECTED_BY" existence validated
DEBUG : RallyEIF::WRK::Connector.block in validate - Rally Connection field_handler validation for "Description" succeeded
DEBUG : RallyEIF::WRK::Connector.block in validate - Rally Connection field_handler validation for "SubmittedBy" succeeded
 INFO : RallyEIF::WRK::Connector.validate - Validation complete
  ANY : RallyEIF::WRK::ConnectorRunner.run_services - Last Run 2014-01-21 21:46:04 UTC  --- Now 2014-01-21 21:48:46 UTC
  ANY : RallyEIF::WRK::ConnectorRunner.process_service - Starting Service COPY_QUALITY CENTER_TO_RALLY
 INFO : RallyEIF::WRK::QCConnection.find_new - find_new query: BG_USER_01 ="" and BG_BUG_ID ="86"
 INFO : RallyEIF::WRK::QCConnection.find_new -   Found 1 New bugs in QC
 INFO : RallyEIF::WRK::Connector.copy_to_rally - Copy Quality Center bug ID 86 to Rally
DEBUG : RallyEIF::WRK::Connector.block in map_fields_to_rally -   Mapping BG_SUMMARY(Test custom field handlers) - to - Name(Test custom field handlers)
DEBUG : RallyEIF::WRK::FieldHandlers::SampleDogsToChiensFieldHandler.transform_in - transform_in() being invoked.
DEBUG : RallyEIF::WRK::Connector.block in map_fields_to_rally -   Mapping BG_DESCRIPTION(1 QC-Chiens 1
2 QC-Chiens 2) - to - Description(1 Rally-Dogs 1
2 Rally-Dogs 2
)
DEBUG : RallyEIF::WRK::FieldHandlers::RallyUsernameToQcUserFieldHandler.transform_in - transform_in() being invoked.
DEBUG : RallyEIF::WRK::Connector.block in map_fields_to_rally - Mapping BG_DETECTED_BY(jpqc11) - to - SubmittedBy([email protected])
 INFO : RallyEIF::WRK::RallyConnection.create_internal - Created DE488
DEBUG : RallyEIF::WRK::QCConnection.update_external_id_fields - set QC Bug BG_BUG_ID: 86 external id field BG_USER_01 --> |16512934672|
DEBUG : RallyEIF::WRK::QCConnection.update_external_id_fields - set QC Bug BG_BUG_ID: 86 external end user id field BG_USER_03 --> |DE488|
 INFO : RallyEIF::WRK::Connector.copy_to_rally - Quality Center bug 86 copied to Rally defect DE488
  ANY : RallyEIF::WRK::ConnectorRunner.process_service - Finished Service COPY_QUALITY CENTER_TO_RALLY
  ANY : RallyEIF::WRK::ConnectorRunner.process_service - Starting Service COPY_RALLY_TO_QUALITY CENTER
 INFO : RallyEIF::WRK::RallyConnection.find_new - Find New Rally defects
DEBUG : RallyEIF::WRK::RallyConnection.find_new - Rally using find_new query: (((QCPR01ExtID = "") AND (Project.Name = "PR01")) AND (FormattedID = "DE352"))
 WARN : RallyEIF::WRK::RallyConnection.block in check_for_warnings -
        Please update your client to use the latest version of the API.
        You can find the latest version at https://rally1.rallydev.com/slm/doc/webservice/index.jsp?version=v2.0.
        API status is Deprecated and will become Not Supported on 2014-May-08.
 INFO : RallyEIF::WRK::RallyConnection.find_new - Found 1 new defects in Rally
 INFO : RallyEIF::WRK::Connector.copy_to_other - Copy DE352 to Quality Center
DEBUG : RallyEIF::WRK::Connector.block in map_fields_to_other - Mapping Name(Test Rally to QC) - to - BG_SUMMARY(Test Rally to QC)
DEBUG : RallyEIF::WRK::FieldHandlers::SampleDogsToChiensFieldHandler.transform_out - transform_out() being invoked.
DEBUG : RallyEIF::WRK::Connector.block in map_fields_to_other - Mapping Description(1 Rally-Dogs 1
2 Rally-Dogs 2) - to - BG_DESCRIPTION(1 QC-Chiens 1
2 QC-Chiens 2)
DEBUG : RallyEIF::WRK::FieldHandlers::RallyUsernameToQcUserFieldHandler.transform_out - transform_out() being invoked.
DEBUG : RallyEIF::WRK::Connector.block in map_fields_to_other - Mapping SubmittedBy([email protected]) - to - BG_DETECTED_BY(jpqc11)
DEBUG : RallyEIF::WRK::QCConnection.create_internal - set all artifact fields
 INFO : RallyEIF::WRK::QCConnection.create_internal - Created bug 89 in QC
DEBUG : RallyEIF::WRK::RallyConnection.block in has_changed? - 89 != is true
 INFO : RallyEIF::WRK::RallyConnection.update_internal - Updating DE352
 INFO : RallyEIF::WRK::Connector.copy_to_other - Rally defect DE352 copied to Quality Center bug 89
  ANY : RallyEIF::WRK::ConnectorRunner.process_service - Finished Service COPY_RALLY_TO_QUALITY CENTER
 INFO : RallyEIF::WRK::QCConnection.disconnect - Disconnected from Quality Center
  ANY : RallyEIF::WRK::ConnectorRunner.run_services - time file written with value of 2014-01-21 21:48:46 UTC
  ANY : RallyEIF::WRK::ConnectorRunner.block in log_service_statistics - x061-85053.xml: 1 items copied from Quality center to Rally
  ANY : RallyEIF::WRK::ConnectorRunner.block in log_service_statistics - x061-85053.xml: 1 items copied from Rally to Quality center
  ANY : RallyEIF::WRK::ConnectorRunner.log_service_statistics - x061-85053.xml: service run took 10 seconds

Feedback

Need more help? The CA Agile Central Community is your one-stop shop for self-service and support. To submit feedback or cases to CA Agile Central Support, find answers, and collaborate with others, please join us in the CA Agile Central Community.