Mappers

Mappers


Mappers

Mapper definitions that transform source data fields to Pricefx format.

When to Use

Mapper type

Use when

API method

loadMapper

Bulk load / replace data

pfx-api:loaddata, pfx-api:loaddataFile

integrateMapper

Upsert (insert or update by key)

pfx-api:integrate

multilevelMapper

Nested/hierarchical data

Multi-level operations


Attribute

Details

Purpose

Define how source fields map to Pricefx fields (rename, transform, convert types)

Format

XML — <mappers> wrapper with one mapper element inside (<loadMapper>, <integrateMapper>, <mapper>)

Naming

By entity or function: product-mapper.xml, customer-mapper.xml. One mapper per file.

Loaded by

Spring context at startup — registered as beans by mapper ID


Mapper Types

Element

Description

<loadMapper>

Used with pfx-api:loaddata and pfx-api:loaddataFile. Bulk inserts.

<integrateMapper>

Used with pfx-api:integrate. Upserts by business key. Define key fields via <businessKey>.

<multilevelMapper>

For nested data structures where one source record produces multiple levels of output.

Expression Types

Expression type

Attribute

Description

body

expression="sourceField" out="targetField"

Direct field copy from source map

simple

expression="${...}" out="targetField"

Camel Simple expression (${header.X}, ${exchangeProperty.X}, ${body[field]})

constant

expression="value" out="targetField"

Fixed literal value

groovy

expression="..." out="targetField"

Groovy script — access source via body['field'], exchange via exchange

Key rules:

  • body is cheapest — use it for simple field rename / copy

  • groovy is most powerful — required for conditionals, calculations, multi-field logic

  • constant for table names, fixed flags, enums

Attributes Reference

Attribute

On

Description

id

mapper

Unique mapper bean ID. Must match file name (e.g., import-products.mapper.xmlid="import-products.mapper").

expression

property

Source expression — meaning depends on type

out

property

Target Pricefx field name

type

property

Expression type: body, simple, constant, groovy

converterExpression

property

Built-in converter name, e.g., stringToDecimal

converter

property

Custom converter Spring bean name (rare — usually want converterExpression)

override

property

If true, overrides the value even if it already exists in target

defaultValue

property

Used by converter when the source value is null or empty

ignoreError

property

If true, swallow conversion errors and continue with null

locale

property

Locale for number/date converters (e.g., en_US, de_DE)

Built-in Converter Expressions

converterExpression

Input → Output

Notes

stringToDecimal

String → BigDecimal

Respects locale and defaultValue

stringToInteger

String → Integer


stringToLong

String → Long


stringToDate

String → Date

Uses format from integration.converters.string-to-date.format

stringToDateTime

String → DateTime

Uses format from integration.converters.string-to-date-time.format

dateToString

Date → String

Uses format from integration.converters.date-to-string.format

stringToBoolean

String → Boolean


booleanToInteger

Boolean → Integer

true→1, false→0

integerToBoolean

Integer → Boolean

1→true, 0→false

Examples

loadMapper — Products from CSV

XML
<mappers>
    <loadMapper id="import-products.mapper">
        <property expression="sku"         out="sku"          type="body"/>
        <property expression="label"       out="label"        type="body"/>
        <property expression="unitOfMeasure" out="unitOfMeasure" type="body"/>
        <property expression="currency"    out="currency"     type="body"/>
        <property expression="listPrice"   out="attribute1"   type="body"
                  converterExpression="stringToDecimal" defaultValue="0"/>
    </loadMapper>
</mappers>

integrateMapper — Customer upsert

XML
<mappers>
    <integrateMapper id="upsert-customers.mapper">
        <businessKey>
            <property expression="customerId" out="customerId" type="body"/>
        </businessKey>
        <property expression="customerId"   out="customerId"   type="body"/>
        <property expression="customerName" out="label"        type="body"/>
        <property expression="country"      out="attribute1"   type="body"/>
        <property expression="region"       out="attribute2"   type="body"/>
    </integrateMapper>
</mappers>

PX (Product Extension) mapper — table name via constant

XML
<mappers>
    <loadMapper id="import-px.mapper">
        <constant expression="Costs" out="name"/>
        <property expression="sku"     out="sku"        type="body"/>
        <property expression="cost"    out="attribute1"  type="body"
                  converterExpression="stringToDecimal" defaultValue="0"/>
        <property expression="vendor"  out="attribute2"  type="body"/>
    </loadMapper>
</mappers>

Groovy expression — conditional mapping

XML
<mappers>
    <loadMapper id="import-with-logic.mapper">
        <property expression="sku"   out="sku"   type="body"/>
        <property type="groovy" out="attribute1"
                  expression="body['status'] == 'ACTIVE' ? body['price'] : 0"/>
        <property type="groovy" out="label"
                  expression="(body['firstName'] ?: '') + ' ' + (body['lastName'] ?: '')"/>
    </loadMapper>
</mappers>

Converter Best Practices

Use converterExpression for built-in converters

XML
<!-- CORRECT — built-in converter -->
<property expression="price" out="attribute1" type="body"
          converterExpression="stringToDecimal" defaultValue="0"/>

<!-- WRONG — 'converter' is for custom Spring beans -->
<property expression="price" out="attribute1" type="body"
          converter="stringToDecimal"/>

Locale-aware number parsing

When source data uses non-US number formats:

XML
<!-- German format: 1.234,56 → 1234.56 -->
<property expression="price" out="attribute1" type="body"
          converterExpression="stringToDecimal" locale="de_DE"/>

Default values for nullable numbers

XML
<property expression="discount" out="attribute3" type="body"
          converterExpression="stringToDecimal" defaultValue="0"/>

Without defaultValue, a null or empty string converts to null in the target. With defaultValue="0", it converts to BigDecimal.ZERO.

Error handling in conversions

XML
<!-- Skip bad records instead of failing -->
<property expression="quantity" out="attribute2" type="body"
          converterExpression="stringToInteger" ignoreError="true"/>

Attribute Value Truncation

When loading data into extension tables (PX, CX, SX), string attribute values may be automatically truncated to prevent Pricefx API errors caused by values exceeding the column size limit.

How It Works

Pricefx extension tables have a fixed database column size for each attribute (typically 255 characters). However, when an extension table has many attributes, the available column size per attribute decreases. The truncation feature dynamically adjusts the maximum allowed string length based on the actual number of attributes configured in the extension table.

The decision logic:

  1. IM fetches the extension table metadata from Pricefx (e.g., configurationmanager.get/productextension) to determine the number of attributes (numberOfAttributes).

  2. If numberOfAttributes >= threshold → values are truncated to max.size characters.

  3. If numberOfAttributes < threshold → values are truncated to the standard 255 character limit.

Configuration

Property

Default

Description

integration.mappers.<TYPE>.attributes.truncate.max.size

70

Maximum string length when the extension table has many attributes (at or above the threshold)

integration.mappers.<TYPE>.attributes.truncate.threshold

50

Number of attributes at which the reduced max.size limit kicks in

integration.mappers.extended.attributes.max.size

10000000

Maximum size for JLTV/JLTV2 extended attribute values

Where <TYPE> is one of: PX, CX, SX.

Default values:

integration.mappers.PX.attributes.truncate.max.size=70
integration.mappers.PX.attributes.truncate.threshold=50
integration.mappers.CX.attributes.truncate.max.size=70
integration.mappers.CX.attributes.truncate.threshold=50
integration.mappers.SX.attributes.truncate.max.size=70
integration.mappers.SX.attributes.truncate.threshold=50

Example

Consider a PX table called Costs with numberOfAttributes=60 (threshold is 50):

  • Since 60 >= 50, the max.size of 70 applies

  • Any string attribute value longer than 70 characters is silently truncated to 70 characters via substring(0, 70)

If the same table had only 30 attributes:

  • Since 30 < 50, the standard 255 character limit applies

Important Notes

  • Truncation applies only to string values. Numbers, booleans, and nulls are not affected.

  • Truncation is a simple substring(0, maxLength) — no ellipsis or warning is added.

  • The extension metadata is cached and refreshed every 10 minutes (configurable via integration.schedulers.mapper-truncate.cache.ms).

  • Standard object types (P, C, SL) always use the 255 character limit — these properties have no effect on them.

  • Applies to loaddata, integrate, and save operations.

Common Pitfalls

  • Mapper IDs must be unique and match the mapper= parameter in route URIs

  • Each file must have the <mappers> wrapper element around the mapper definition — do NOT use <beans>, <beans:beans>, or XML declarations

  • Use groovy expressions for complex transformations, body for simple field mapping

  • Built-in type converters (e.g., stringToDecimal) must use the converterExpression attribute, not converter. The converter attribute is only for custom Spring bean references.

  • One mapper per file — do not put multiple mappers in a single file

See Also

  • Routes — Mappers are referenced in routes via mapper= parameter

  • Filters — Filters select data, mappers transform it

  • Converters — Type converters used in mapper expressions

  • pfx-api Component — loaddata and integrate methods use mappers