Technical article
PlatformHttp v2.0.0: one HTTP entry, pluggable DTS transforms via SPI and DataSonnet
The PlatformHttp v2.0.0 sample shows how a stable HTTP Listener entry fans one request out to multiple named transforms: a unified invokeDtsTransform call, third-party providers loaded at runtime from services/TransformDS via Java SPI, and DataSonnet import keeping mapping rules modular.
Orchestrate many transforms without patching the core
Integration routes often need several business transforms inside one request, plus extension points that ship separately from the runtime. PlatformHttp v2.0.0 answers with four pieces: a stable HTTP Listener entry, a unified invokeDtsTransform invocation, SPI loading from services/TransformDS, and shared DataSonnet function imports. The result: one request produces multiple transform outputs, route XML never names a provider class, and rolling out a new extension is a jar drop — not a core patch.
A stable entry and a unified invocation
The endpoint is assembled from the two properties files every LightESB service carries — server.port and HTTP.Listener from common.config.properties, service.version from service.config.properties — yielding POST http://localhost:18081/2.0.0/api/demo:
<from uri="undertow:http://0.0.0.0:{{server.port}}/{{service.version}}/api/demo" />
# common.config.properties
server.port=18081
HTTP.Listener=true
# service.config.properties
service.version=2.0.0Inside the route, four method calls on the commonFunctions bean run four named transforms against the same body. The route stays decoupled from provider class names — only the transform name matters:
<method ref="commonFunctions" method="invokeDtsTransform('transformComplexOrder', ${body})" />
<method ref="commonFunctions" method="invokeDtsTransform('transformOrderSummary', ${body})" />
<method ref="commonFunctions" method="invokeDtsTransform('transformCustomerSnapshot', ${body})" />
<method ref="commonFunctions" method="invokeDtsTransform('transformRiskTags', ${body})" />SPI loading from services/TransformDS
Third-party transform implementations arrive as jars dropped into services/TransformDS. The runtime chain is deterministic:
- Scan the services/TransformDS directory.
- Load every *.jar found there.
- Discover providers through ServiceLoader<LightesbDtsExtension>.
- Build the transformName -> provider mapping from each provider's supportedTransforms().
- Resolve same-name conflicts by priority() — the higher priority wins.
Input mapping scripts stay modular too: a DataSonnet script can import a shared function library, so formatting logic lives in one place while the main script keeps only mapping intent:
local lib = import 'lightesb-camel-app/TransformDS/common-functions.ds';
# common.config.properties
input-transform=true
input-transform.file=input-transform-with-import.dsReal request, real response shape
From the repository root, post the bundled test.json to the endpoint:
curl -X POST "http://localhost:18081/2.0.0/api/demo" \
-H "Content-Type: application/json" \
--data-binary "@lightesb-camel-app/PlatformHttp/v2.0.0/test.json"The route assembles all four transform outputs plus two shared-function results into one body. A jq one-liner verifies the four transform keys:
{ "complexOrder": "{...}", "orderSummary": "{...}",
"customerSnapshot": "{...}", "riskTags": "{...}",
"formattedAmount": "", "validatedField": "" }
curl -s -X POST "http://localhost:18081/2.0.0/api/demo" \
-H "Content-Type: application/json" \
--data-binary "@lightesb-camel-app/PlatformHttp/v2.0.0/test.json" | jq '{complexOrder, orderSummary, customerSnapshot, riskTags}'When something does not resolve
No DTS extension found
Check that the transform name matches supportedTransforms() exactly, that the extension jar sits under services/TransformDS, and that the SPI descriptor path and class names are correct.
Same transform name twice
If multiple providers claim one transformName, the runtime picks the implementation with the higher priority().
Endpoint unreachable
Verify HTTP.Listener=true, server.port=18081, and that the request path includes the version segment /2.0.0/api/demo.
DataSonnet import fails
Verify input-transform.file=input-transform-with-import.ds and that the imported library path is valid for the runtime resolution model.