Import CSV to Data Source (DMDS)
Overview
This example demonstrates how to import data from a CSV file into a Pricefx Data Source (object type DM with dsUniqueName). Data Sources (also known as Data Marts or DMDS) are flexible storage tables used for pricing calculations. This example includes the critical onCompletion flush step that finalizes the data load and makes records available for use.
Files
routes/import-csv-to-datasource.xml
<routes xmlns="http://camel.apache.org/schema/spring">
<route id="import-csv-to-datasource">
<from uri="file:{{import.datasource.directory}}?{{archive.file}}&{{read.lock}}"/>
<log message="Processing data source file: ${header.CamelFileNameOnly}" loggingLevel="INFO"/>
<split aggregationStrategy="recordsCountAggregation" streaming="true">
<tokenize token="
" group="10000"/>
<to uri="pfx-csv:unmarshal?skipHeaderRecord=true"/>
<to uri="pfx-api:loaddata?objectType=DM&dsUniqueName=Product&mapper=import-csv-to-datasource.mapper"/>
</split>
<log message="Data source import complete. Total records: ${header.PfxTotalInputRecordsCount}" loggingLevel="INFO"/>
<onCompletion onCompleteOnly="true">
<log message="Flushing data source DMDS.Product" loggingLevel="INFO"/>
<to uri="pfx-api:flush?dataFeedName=DMF.Product&dataSourceName=DMDS.Product"/>
<log message="Data source DMDS.Product flushed successfully" loggingLevel="INFO"/>
</onCompletion>
</route>
</routes>
mappers/import-csv-to-datasource.mapper.xml
<mappers>
<loadMapper id="import-csv-to-datasource.mapper">
<body in="sku" out="key1"/>
<body in="region" out="key2"/>
<body in="effectiveDate" out="key3"/>
<body in="listPrice" out="value1"/>
<body in="costPrice" out="value2"/>
<body in="minPrice" out="value3"/>
<body in="discount" out="value4"/>
<body in="margin" out="value5"/>
</loadMapper>
</mappers>
config/application.properties (snippet)
# Import directory for data source CSV files
import.datasource.directory=/data/imports/datasource
How It Works
-
File Pickup: The
file:component monitors the configured directory for CSV files.{{archive.file}}moves processed files to a timestamped archive;{{read.lock}}waits until the file is fully written before reading. -
Splitting: The
splitwithtokenize token=" " group="10000"breaks the file into batches for streaming processing. This is essential for large data source files that can contain millions of rows. -
CSV Unmarshalling:
pfx-csv:unmarshalparses each batch into a list of maps. -
Loading to Pricefx:
pfx-api:loaddatawithobjectType=DManddsUniqueName=Producttargets the specific Data Source table named "Product". The mapper maps CSV columns to Data Source key and value fields. -
Flush on Completion: The
onCompletion onCompleteOnly="true"block runs after the route completes successfully. Thepfx-api:flushcall finalizes the data load by flushing the data feed (DMF.Product) and data source (DMDS.Product). This step makes the loaded records available for use in pricing logic.
Common Pitfalls
-
Missing flush: Without the
pfx-api:flushstep, loaded data remains in a staging state and is not available for pricing calculations. Always include a flush after loading to a Data Source. -
Flush naming convention: The
dataFeedNameuses the prefixDMF.and thedataSourceNameuses the prefixDMDS., both followed by the same unique name used indsUniqueName. For example, ifdsUniqueName=Product, thendataFeedName=DMF.ProductanddataSourceName=DMDS.Product. -
onCompletionplacement: TheonCompletionblock must be placed inside the<route>element but outside the<split>block. Placing it inside the split will cause it to execute after every batch instead of once at the end. -
onCompleteOnlyvs default: UseonCompleteOnly="true"to ensure the flush only runs on successful completion. Without this flag, the flush would also run if the route fails, potentially flushing incomplete data. -
No
businessKeysfor DMDS: Unlike Products and Customers, Data Source loads typically do not usebusinessKeys. Each flush replaces the entire data set. If you need incremental loads, consider usingdirect2ds=trueinstead. -
Key/Value field naming: Data Sources use
key1-key6for dimension fields andvalue1-value30for measure fields. The field names in Pricefx Administration determine what each key/value represents.