By nghxni

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.0

Inside 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:

  1. Scan the services/TransformDS directory.
  2. Load every *.jar found there.
  3. Discover providers through ServiceLoader<LightesbDtsExtension>.
  4. Build the transformName -> provider mapping from each provider's supportedTransforms().
  5. 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.ds

Real 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.

Transform components guidePlatformHttp v2.0.0 service