Skip to content

FreeMarker Ingestion Reference

In the Import pipeline (such as Hierarchy Mapping), the FreeMarker Engine runs under version 2.3.23.

To maintain security and optimize parser performance, the data model available to FreeMarker in the import pipeline is restricted to exactly two global variables alongside your source document dataset:

classDiagram
class ImportFreemarkerDataModel {
+protocolLogger protocolLogger
+Map valueMappings
}
class ProtocolLogger {
+info(String key, String msg, Object targetEntity)
+warn(String key, String msg, Object targetEntity)
+error(String key, String msg, Object targetEntity)
+fatal(String key, String msg, Object targetEntity)
}
class ValueMapping {
+mapValue(String inputValue) String
+mapAttribute(String inputValue) String
+mapGroup(String classificationId, String groupId) Map
}
ImportFreemarkerDataModel --> ProtocolLogger : Injects
ImportFreemarkerDataModel --> ValueMapping : Injects

The protocolLogger variable connects your FreeMarker templates directly to the PXM Import Reporting pipeline. It lets you write operational logs and error notifications directly into the user’s import report summary.

  • protocolLogger.info(String key, String msg) / protocolLogger.info(String key, String msg, Object targetEntity)
  • protocolLogger.warn(String key, String msg) / protocolLogger.warn(String key, String msg, Object targetEntity)
  • protocolLogger.error(String key, String msg) / protocolLogger.error(String key, String msg, Object targetEntity)
  • protocolLogger.fatal(String key, String msg) / protocolLogger.fatal(String key, String msg, Object targetEntity)
  • key: A category identifier denoting the affected component (e.g., "product", "price", "classification").
  • msg: The descriptive log message.
  • targetEntity (Optional): Passing the parsed domain entity object allows the PXM logger to extract its primary identifier, creating direct links to the faulty record in the UI report.
<#if !SourceSchema.product.catalogNumber??>
${protocolLogger.warn("product", "Product is missing a catalog reference. Proceeding with fallback.", SourceSchema.product)}
</#if>

The valueMappings variable provides direct access to all active Value Mappings configured in PXM. It allows you to transform incoming supplier codes or category names into internally approved PXM values on-the-fly.

valueMappings is a map keyed by the unique ValueMappingId. Accessing a specific mapping returns a helper object containing the mapping API.

  • mapValue(String inputValue) (or mapAttribute(String inputValue)): Translates a raw input string value to the mapped PXM equivalent.
  • mapGroup(String classificationId, String groupId): Maps an external classification group. Returns a map containing:
    • "classificationId": The target classification ID.
    • "groupId": The target classification group ID.
{
"color": "${valueMappings["color_supplier_to_internal"].mapValue(SourceSchema.product.color_code)}"
}
<#assign mappedGroup = valueMappings["group_external_to_internal"].mapGroup("ECLASS12", SourceSchema.product.category_code)>
{
"classificationId": "${mappedGroup.classificationId}",
"classificationGroupId": "${mappedGroup.groupId}"
}

Complete Step-by-Step Configuration Example

Section titled “Complete Step-by-Step Configuration Example”

To help you get started, here is a complete step-by-step example showing how to build an import channel and write a template to process hierarchical files:

  1. Go to the Import Channels dashboard in PXM and click Create Channel.
  2. Set the Communication Channel to REST Web Service.
  3. Configure the endpoints and variables as shown in the REST Web Service section.

In the Import Format tab of your channel, select Hierarchy Mapping and paste the following FreeMarker script to map nested supplier categories to internal catalog structures:

<#-- Initialize template variables -->
<#assign supplier = SourceSchema.supplier.name>
{
"productId": "${SourceSchema.product.partNumber}",
"catalogId": "MasterCatalog",
"supplierId": "${supplier}",
"attributeValues": [
<#-- Iterate over nested localized description objects -->
<#list SourceSchema.product.localizedDetails as details>
{
"attribute": "LongDescription",
"language": "${details.lang}",
"values": [
"${details.text}"
]
}<#sep>,</#sep>
</#list>
],
"classificationGroups": [
<#-- Map incoming categories to internal PXM hierarchy using Value Mappings -->
<#assign mappedCategory = valueMappings["eclass_to_pim_groups"].mapGroup("ETIM9", SourceSchema.product.category)>
{
"classificationId": "${mappedCategory.classificationId}",
"groupId": "${mappedCategory.groupId}"
}
]
}
  1. Click the Result tab to execute a dry run against a sample payload.
  2. If there are missing references or parsing warnings, they will be logged via protocolLogger and visible under the execution results panel.