8 Source/Target Mapping

Launch Integration uses a mapping service which enables you to create proxy API that can pull data into Launch and push data into external applications. The mapping service also allows customers to modify the seeded mapping rules using extensions. For more information, see "Handling Extensions".

API Mapping

The API mapping enables you to create a proxy API that can map APIs between the source and target systems.

The section in the API mapping are:
  • Source API Mapping
  • Target API Mapping

Source mapping allows you to orchestrate calling APIs on a source system and then map them to a set of target APIs. In case of publishing, the source is Launch and target is the external application and is vice versa in the case of migration.

Refer to respective OAS to understand more on the APIs.

Data Mapping

Data mapping enables you to create mappings between the target API schema and the logical source schema created using the source API Mapping. The mapping is done using JSON path expressions. The framework provides additional functions to simplify complex mapping that can't be supported using the JSON path.

You can use these built-in functions to map third-party catalog consuming apps using the supported functions and application constants.

Supported Functions

Table 8-1 lists the functions available for use in the data transformation, refer to the description column to understand the use of a function.

Table 8-1 Supported Functions

Function Name Signature Description

@toUpper

@toUpper(json path)

Converts data to upper case.

@toDataType

@toDataType(value json path, data type json path, boolean true value, boolean false value)

Converts data to data type if the source data doesn't conform to the given data type or uses custom data type

@toFlatten

@toFlatten(source json path, relative depth json path)

Flattens an object or array to the given depth.

@indexOf

@indexOf(array json path)

Returns index of an array element.

@replaceValue

@replaceValue(jsonPath/ function/default constants, header key)

Uses header value passed in the request.

The name of the parameters should be in this form - User- Project-Name.

The first letter and the subsequent letters after hyphen(-) must be capitalized.

Examples: @replaceValue($,User- Project-Id) # correct @replaceValue($,User-Project- Name) # correct @replaceValue($,user-project-name)

# Incorrect

@invokeRest

@invokeRest(function name, argument list...)

Tenant implements end point and configures it in the Industry Framework.

@valueMap

@valueMap(condition json path/function, default, json path/function, source, target)

Maps the value found at the third argument using a variable number of source/target values.

Keep in mind that when the target field uses an Open API type of "oneOf": [...], this function will not be able to cast mapped values to types unless the target type is declared with an explicit Open API "type" instead of "oneOf".

@conditionValueMap

@conditionValueMap (json path/function, default, trueValue, falseValue)

Returns trueVal if the first argument resolves to anything non- null that is not an empty list.

Returns falseValue if the first argument resolves to an empty list.

Returns the default value if the first argument resolves to null.

@defaultValue

@defaultValue (json path/function, default value)

Returns the value found after evaluating the first argument.

Returns the default value if the first argument is null.

@distinctValues

@distinctValues(json path array, arg1, arg2, ...)

Returns the distinct values based on the parameter passed. The first argument should return an array. The other arguments contain fields that are used to find distinct elements.

@alterValue

@alterValue(condition json path, json path or value, mathematical operator, json path or value, precision(optional), rounding mode(optional))

It performs a mathematical operation on its operands and produces a number according to the specified precision and rounding mode.

@toArrayLength

@toArrayLength(condition json path, json path or function)

It calculates the length of an array and produces a number according to that.

@concatValues

@concatValues(condition, arg1, arg2, ...)

Returns the concatenated string based on the parameters passed.

The 1st argument (function or JSON path) is a condition. If the first argument evaluates to not null, then the function will return the concatenated value else it will return null.

@compareValue

@compareValue(condition json path, json path or value or header param or query param, relational operator, json path or value, dataType optional)

It compares the left and right operands using the relational operators like (<,>,<=,>=,==,!=), based upon the dataType mentioned and returns a Boolean value as result.

@conditionalConvertValue

@conditionalConvertValue(conditionJson Path, jsonPath, regex, index, case identifier)

This function is used to split and convert the case of an input text passed in its 2nd arg to the user requested case passed in 3rd arg, 4th arg, and 5th arg.

@convertCase

@convertCase(condition json path/function, json path/function/constants, case identifier)

This function is used to split and convert the case of an input text passed in its2nd arg to the user requested case passed in 3rd arg.

@dateConverter

@dateConverter(condition 'json path',date 'json path', default date(optional), source date format(optional), target date format(optional))

Based on the condition, it converts date from source format to target format if provided or uses default date format. If the date resolves to null and then returns default date converted in target format, if default date is also null then returns null.

@evaluateDataType

@evaluateDataType( jsonPath, dataType, format Optional)

It checks if the value of that jsonPath returns the specified data type or not. In case of date format has to be passed.

@filterArray

@filterArray(conditionalJsonPath, filteredArrayJsonPath, minLengthForComparing, operator, additionalCondition)

Filter the array based on the condition provided.

@getArrayElementByIndex

@getArrayElementByIndex(condition json path or function, json path or function, integer constant or json path or function returning integer index)

It returns an array element present at specified index passed in 3rd argument.

@getFilteredArrayElement

@getFilteredArrayElement(condition,jsonpath, filterCriteria, index, fieldsJsonpath)

Based on the condition, it substitutes the search string with replace string in the data and returns the transformed data.

@infixToPrefix

@infixToPrefix($, $.['stringExpression'], operator_map('REQU IRES','req','NOT','!'), type_map('REQUIRE S','binary','!','unary'), operand_map(), exp_json_path($.id, productId), apply_Siebel_Format (true))

This function is used to convert infix expression to its prefix form.

@objectToStringExp

@objectToStringExp (jsonPath, keyValueSep, fieldSep, mode, [replaceString], [enclosedBy])

Function to convert a json object to a string, with the ability to ignore empty fields and separate fields, values, and field-value pairs, as well as wrap each field value pair with a string.

@prefixToInfix

@prefixToInfix(condition json path, json path, source_system_siebel (true/false), operator_map('source-system- operator','eqv- target-system- operator', ….…. ),type _map('source- system- operator','operator- type', ….... ),operand _map('custom- source-system- operand','regex-exp-to-be-used or way to resolve custom operand in target system', ….... ),exp_json_path(entity(entity _Type_Identifier_In_ Target_System, JsonPath to identify ID in stitched payload), ... ))

This function is used to convert prefix expression to infix expression.

@splitString

@splitString(conditionJsonPath, jsonPath, regex, defaultValue, index)

It splits any string based on a regex and returns list of values if no index given in the argument else returns that specific value based on the index mentioned in the argument.

@substituteValues

@substituteValues(condition 'json path or function', data 'json path or value or function' , search string 'json path or value or function' , replace string 'json path or value or function', ….…....)

Based on the condition, it substitutes the search string with replace string in the data and returns the transformed data.

Supported Application Constants

Table 8-2 lists the application constants available for use in data transformation, refer to the description column to understand the use of respective application constants.

Table 8-2 Supported Application Constants

Name Sample Payload Description

@jobId

"name": { "type":
"string",
"x-oracle-map-data": {
"json_path": "@concatValues($,-
,SM,@jobId)", "mapType": 
"TO_FIELD"
 }
}

The current job ID.

@applicationName

"source":{ 
"type": "string",
"x-oracle-map-data": { 
"default": 
"@applicationName" 
 }
},

Returns the name of the source system.

@epochTime

"startDate":{
"type":"string",
"format":"date-time",
"x-oracle-map-data":{
"default":
"@epochTime"
 }
}

Returns the epoch time based on system time.

@recordNum

"id":{
"type":"string",
"x-oracle-map-data":{
"mapType":
"TO_FIELD","concat":
  {
    "separator":"-",
    "fields":[
    "@const(Conditon)",
    "@recordNum"
   ] 
  }
 }
}

Returns the number of records when the JSON path returns multiple objects in API map.

@replace(key)

"source_request_spec": {
"source_api_path": "/siebel/v1.0/data/Price 
List/Price List", "source_request_type": "GET",
 "distinct_key_json_path": "$.Id",
 "select_json_path": "$.items",
"query_param": [
  {
   "key": "PageSize",
   "value": "@replace(batchSize)"
  }
 ]
}

Replaces a value from given header key.

@pathParam(key)

{
"source_api_path": "/siebel/v1.0/data/Volume 
Discount/Volume Discount/{id}/Volume
Discount Item",
"source_request_type": "GET", 
"query_parameter": 
"@pathParam(id)", 
"query_value_json_path": "$.Id",
...
}

Used in query map to pass value for a path parameter key.

Supported Templates

The API configuration allows you to define template files for the source API calls. They are configured as part of the mapping file definition.

Templates used by Siebel CRM

Table 8-3 lists template files that are referenced by the source API configuration during the migration event.

Table 8-3 Templates used by Siebel CRM

Template Description

catalogPOSTTemplate.json

Used to retrieve catalog from Siebel.

attributePOSTTemplate.json

Used to retrieve attributes from Siebel.

classPOSTTemplate.json

Used to retrieve product class from Siebel.

plPOSTTemplate.json

Used to retrieve product lines from Siebel.

productPOSTTemplate.json

Used to retrieve product from Siebel.

promotionPOSTTemplate.json

Used to retrieve promotion from Siebel.

skuPOSTTemplate.json

Used to retrieve Smart Part Number from Siebel.

adjustmentGroupPOSTTemplate.json

Used to get Product-Based Adjustment for discount matrices from Siebel.

bulkPromotionPostTemplate.json

Used to get bulk of promotions from Siebel.

productComponentsPOSTTemplate.json

Used to get the CP full structure from Siebel.

recommendationRulePOSTTemplate.json

Used to get recommendation rules from Siebel.

promotionPostIdsTemplate.json

Used during nested job processing for Siebel promotion.

ProductPostIdsTemplate.json

Used during nested job processing for Siebel products.

Table 8-4 Templates used by Siebel CRM

Template Description

catalogIDTTemplate.json

Used to retrieve Catalog ID from Siebel.

productClassIDTemplate.json

Used to retrieve Product Class ID from Siebel.

productLineIDTemplate.json

Used to retrieve Product Line ID from Siebel.

productIDTemplate.json

Used to retrieve Product ID and Promotion ID from Siebel.

Managing Mapping File Versions

Oracle ships the two seeded grammar files:
  • One-time migration: the siebel_launch.json file that contains the mapping with source as Siebel and target as Launch.
  • Publish to Siebel: the launch_siebel.json file that contains the mapping with source as Launch and target as Siebel.
You can retrieve the mapping file using the following command:
GET - {{APIGW}}/mappingSchema/cx/industry/apiIntegration/v1/mappingSchema
     Headers to be passed:   
         Source System  <<SourceName>>  
         X-Destination-System <<DestinationName>>

Any additional extensions that you need to bring into the mapping is done using the versioning of the mapping file using the seeded grammar file as the starting point.

Note:

The seeded files should never be modified as all release updates make it into these files.

To use versioning of the grammar files you can pass a unique version as part of Mapping APIs using the X-Version header. But it’s optional. If the header is not passed, the default version of the mapping is used.

After creating the grammar files using different versions, you can pass the desired version in the header X-Version to run the migration job. The migration and publish job will identify the grammar file by the version and will use it to run the job. For more information on how to extend using the seeded grammar files, refer to the "Handling Extensions" section below.

Handling Extensions

It is quite common for Siebel customers to have extensions to Product definitions to meet their business needs.

Mapping definitions are preconfigured for both publish and migration with the required template files for the standard Siebel fields. The seeded mapping can be updated, or new mapping configurations can be created using the REST APIs. This can also be done using the Catalog Sync UI.

The steps to add extension in grammar files:

1. All extensions to Launch for the identified Siebel extensions to product definitions to be done using Launch Extensibility. See Launch Cloud Service Implementation Guide for more details. For example, the extensions are made to productOfferingOracle.yml file to create productOfferingCustomer.yml file.

2. The seeded grammar file can be retrieved by using get Grammar call as below.

a. For migration related changes the X-Source-System should be “siebel” and X-Destination- System should be “launch”.

b. For publishing related changes the X-Source-System should be “launch” and X-Destination- System should be “siebel”.

GET - {{APIGW}}/mappingSchema/cx/industry/apiIntegration/v1/mappingSchema
     • Headers to be passed:
        o X-source systems <<SourceName>>
        o X-Destination-System <<DestinationName>>

3. Once the grammar files are retrieved, the next step is to make the mapping edits:

For example, a new @type is defined as productOfferingCustomer, the changes in target_spec_request will be addition of new target_spec_request

Search for componentName of “SiebelProduct” and copy the entire Json Object as it is into the new file and change the following two fields :

"eligibility_check_json_path": "$..projectItems[?(@.isBundle == 'false' && @.['@referredType'] == ‘productOfferingCustomer’)]",
"source_data_path": "$..projectItems[?(@.isBundle == 'false' && @.['@referredType'] == ‘productOfferingCustomer’)]",

Also change the component name and give a new Name:

"componentName": " productOfferingCustomer ",
"name": “productOfferingCustomer"

Define this newly created target_request_spec just below siebelProduct for convenience.

Define the component created above in component section:

Use all_of of openAPI to refer Siebel product in new component as below:

" productOfferingCustomer ": {
 "title": "SiebelProductContainer", 
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/SiebelProduct"
},
{
"properties": {

Maintain the tree hierarachy of parent (siebelProduct in the properties, not necessarily all the properties in the tree) and add only the additional extended field.

" productOfferingCustomer ": { 
"title": "SiebelProductContainer", 
"type": "object",
"allOf": [
   {
    "$ref": "#/components/schemas/SiebelProduct"  
   },  
   {
     "properties": { 
      "SyncChild": {
      "type": "string",
        "x-oracle-map-data": { 
         "json_path": "$.dummyField",
         "mapType": "TO_FIELD", 
         "default": "Y"
   }
  },
  "SiebelMessage": { 
   "type": "object",
   "title": "SiebelMessage", 
   "x-oracle-map-data": {
    "json_path": "$", 
    "mapType": "TO_OBJECT"
   },
   "properties": { 
    "ListOfSWIProductIntegrationIO": { 
    "type": "object",
     "title": "ListOfSWIProductIntegrationIO", 
     "x-oracle-map-data": {
      "json_path": "$", 
      "mapType": "TO_OBJECT"
    },
    "properties": {
     "SWI Product Integration VBC": { 
      "type": "array",
      "x-oracle-map-data": {   
       "json_path": "$", 
       "mapType": "TO_ARRAY"
    },
    "items": {
     "type": "object", 
     "properties": {
      "ListOfSWI Product Definition VBC": { 
       "type": "object",
       "title": "ListOfSWI Product Definition VBC", 
       "x-oracle-map-data": {
        "json_path": "$", 
        "mapType": "TO_OBJECT"
      },
     "properties": {
      "SWI Product Definition VBC": { 
       "type": "array",
       "x-oracle-map-data": {
        "json_path": "$",
        "mapType": "TO_ARRAY"
       },
       "items": {
        "type": "object",
        "properties": {    
        "ExtendedField": {
         "type": "string",
         "x-oracle-map-data": {
          "mapType": "TO_FIELD",
          "json_path": "$.sourceResponse.productOfferingTMF.id"
         }
        },

In the above example, a new field named ExtendedField is added inside SWI Product Definition VBC.

Existing fields will be inherited from SiebelProduct , only the tree hierarchy needs to be maintained.

The created grammar file with changes needs to be uploaded to UCM. It is advisable to upload the created grammar file starting with V1 version and then incrementing the version for every subsequent changes , this can be done as below:

PUT - {{APIGW}}/mappingSchema/cx/industry/apiIntegration/v1/mappingSchema
     • Headers to be passed:
        o X-Source-System <<sourceName>>
        o X-Target-System <<targetName>>
        o X-Version V1
     • Body to be passed
        o File. <<file to be uploaded>>

Once the grammar file is uploaded to V1 version , destination needs to updated as below:

PATCH –{{launch_URL}}/crmRestApi/resources/11.13.18.05/atcPublishWorkspaceDestinations
    • Body to be passed
    {
      "DestVersion": "V1"
    }

All the template file mentioned in section Templates used by Siebel CRM also needs to be uploaded with X-Version as V1.

POST – {{FA_APIGW}}/mappingSchema/cx/industry/apiIntegration/v1/template
      • Headers to be passed
         o X-Source-System- <<SourceName>>
         o X-Target-System- <<targetName>>
         o X-Version–V1
      • Body to be passed
         o File- <<file to be uploaded>>
    

After updating template file, publish can be performed.

Versioning:

The versions of grammar file can be maintained by passing X-Version as mentioned in previous section.

To create a new version of grammar file, first call get grammar

GET - {{APIGW}}/mappingSchema/cx/industry/apiIntegration/v1/mappingSchema
       • Headers to be passed
         o X-Source-System- <<SourceName>>
         o X-Destination-System- <<DestinationName>>
    

After getting the grammar file, add the changes using all_of openAPI as explained in previous section, after changes are done upload the grammar at specified version. Name the file as <<source>>_<<destination>>.json

PUT - {{APIGW}}/mappingSchema/cx/industry/apiIntegration/v1/mappingSchema
     • Headers to be passed:
        o X-Source-System <<sourceName>>
        o X-Target-System <<targetName>>
        o X-Version V1
     • Body to be passed
        o File. <<file to be uploaded>>

The destination needs to be updated.

PATCH – {{launch_URL}}:443/crmRestApi/resources/11.13.18.05/atcPublishWorkspaceDestinations
    • Body to be passed
    {
      "DestVersion": "V1"
    }

Once grammar is uploaded, you can start publishing.

Supported UCM Calls

UCM is the content store where the grammar files are stored in folders with versioning of the changes. You can create a new mapping file, retrieve the latest to make updates and upload the changes made..

Create Mapping OAS File
POST - {{APIGW}}/mappingSchema/cx/industry/apiIntegration/v1/mappingSchema
  • Headers to be passed:
     o X-Source-System <<sourceName>>
     o X-Target-System <<targetName>>
  • Body to be passed
    o File. <<file to be uploaded>>

For more details on header key usage, see Supported Header Keys in this guide.

Update Mapping OAS File
PUT - {{APIGW}}/mappingSchema/cx/industry/apiIntegration/v1/mappingSchema
• Headers to be passed:
   o X-Source-System <<sourceName>>
   o X-Target-System <<targetName>>
• Body to be passed
   o File. <<file to be uploaded>>
Create Template File
POST – {{FA_APIGW}}/mappingSchema/cx/industry/apiIntegration/v1/template
• Headers to be passed
     o X-Source-System- <<SourceName>>
     o X-Target-System- <<targetName>>
     o X-Version- V1
• Body to be passed
     o File- <<file to be uploaded>>
Update Template File
PUT – {{FA_APIGW}}/mappingSchema/cx/industry/apiIntegration/v1/template
• Headers to be passed
     o X- Source-System - <<SourceName>> 
     o X-Target-System - <<targetName>> 
     o X-Version - V1
• Body to be passed
     o File - <<file to be uploaded>>

Troubleshooting Integration Errors

This section describes the common issues that could occur either during catalog sync or during publish or migration.

Table 8-5 Troubleshoot Integration Errors

Error Scenario Error Description Troubleshooting Tips

Publish is successful, however Product is not created in Siebel CRM.

No error in the UI will be shown.

Offers with at least one offer only will be published to Siebel CRM. Ensure that the offer has pricing defined.

Publish does not get initiated

HTTP 404 error in browser console

Ensure that Destination is configured correctly.

Publish fails with error

Processing Failure

Use REST APIs in test mode to analyze further.

Publish status of the initiative does not change even after running for a long time.

No visible error reported.

PATCH the publish job as FAILED using REST API and then republish the initiative.

Gateway timeout in test mode.

Launch REST APIs returns error when run in test mode.

Publish - filter the results by adding the header Component-Name

Migration – Run the migration job in Async- Mode.

Migration fails with error "A bundle product offer must be provided when the isBundle is true"

Not Applicable

Siebel CRM supports Customizable Product without having any component products. But Launch does not allow to create a Bundle Offer without adding any component products to it.

Migration fails with error “The subresource characteristic entity with the (xyz) value combination already exists. Enter unique values.”

This issue comes up when an attribute is used more than once in the product class. Here xyz in error msg is the attribute name being used more than once in a class.

In Siebel, attribute is a top-level entity and a class can have same attribute definition more than once with different name. But Launch does not allow to use same attribute definition more than once. Hence migration fails.

For additional information on errors on Publish to Siebel CRM, see the Siebel CRM REST API Guide https://www.oracle.com/documentation/siebel-crm-libraries.html.