VOOZH about

URL: https://dev.to/nghxni/lightesb-platformhttp-v200-dts-transform-with-spi-and-datasonnet-1836

⇱ LightESB PlatformHttp v2.0.0: DTS Transform with SPI and DataSonnet - DEV Community


TL;DR

  • PlatformHttp@v2.0.0 exposes one HTTP Listener request entry: POST /2.0.0/api/demo.
  • The route calls invokeDtsTransform(...) four times to run multiple transform names in one request.
  • Third-party transform implementations are loaded from services/TransformDS via Java SPI.
  • Input mapping scripts can still reuse DataSonnet libraries through import, which keeps rules modular.

Metadata

  • Applicable Version: PlatformHttp@v2.0.0
  • Related Service: PlatformHttp@v2.0.0@complex-json-transform-route.xml

Background and Goal

In many integration projects, teams need both:

  • route-level orchestration for multiple business transforms
  • runtime-pluggable extension points without changing core LightESB code

PlatformHttp v2.0.0 demonstrates a practical approach:

  1. keep a stable HTTP Listener request entry
  2. use a unified transform invocation API (invokeDtsTransform)
  3. load third-party transform providers from services/TransformDS
  4. keep DataSonnet scripts maintainable with shared function imports

Route and Configuration Breakdown

1) HTTP Listener request entry

From lightesb-camel-app/PlatformHttp/v2.0.0/complex-json-transform-route.xml:

<from uri="undertow:http://0.0.0.0:{{server.port}}/{{service.version}}/api/demo" />

From lightesb-camel-app/PlatformHttp/v2.0.0/common.config.properties:

server.port=18081
HTTP.Listener=true

From lightesb-camel-app/PlatformHttp/v2.0.0/service.config.properties:

service.version=2.0.0

Resulting endpoint:

  • POST http://localhost:18081/2.0.0/api/demo

2) Unified DTS transform invocation in route

The route invokes:

<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})" />

This gives two key advantages:

  • one request can produce multiple transform outputs
  • route code is decoupled from specific provider class names

3) SPI loading model and deployment location

Based on docs/23-third-party-dts-extension-guide.md and services/TransformDS/README.md, the runtime chain is:

  1. scan services/TransformDS
  2. load *.jar
  3. discover providers via ServiceLoader<LightesbDtsExtension>
  4. build transformName -> provider mapping by supportedTransforms()
  5. resolve conflicts by priority()

Operationally, this means:

  • publish extension jars to services/TransformDS
  • route still calls invokeDtsTransform('<transformName>', ...)
  • no core LightESB source patch is required for normal extension rollout

4) DataSonnet import for reusable transform rules

From lightesb-camel-app/PlatformHttp/v2.0.0/input-transform-with-import.ds:

local lib = import 'lightesb-camel-app/TransformDS/common-functions.ds';

From lightesb-camel-app/PlatformHttp/v2.0.0/common.config.properties:

input-transform=true
input-transform.file=input-transform-with-import.ds

This keeps the script focused on mapping intent, while common formatting logic is centralized in shared functions.

Request and Response Examples

Request example

Run from repository root:

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"

Response example (shape)

The route transforms response body into:

{"complexOrder":"{...}","orderSummary":"{...}","customerSnapshot":"{...}","riskTags":"{...}","formattedAmount":"","validatedField":""}

Quick verification:

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}'

Common Issues and Troubleshooting

1) No DTS extension found

Check:

  • target transform name exactly matches supportedTransforms()
  • extension jar is under services/TransformDS
  • SPI descriptor file path and class names are correct

2) Extension conflict (same transform name)

If multiple providers claim one transformName, runtime chooses higher priority().

3) Endpoint is unreachable

Check:

  • HTTP.Listener=true
  • server.port=18081
  • request path includes version segment /2.0.0/api/demo

4) DataSonnet import resolution failure

Check:

  • input-transform.file=input-transform-with-import.ds
  • imported library path is valid for your runtime resolution model

Summary

PlatformHttp v2.0.0 presents a practical DTS architecture for enterprise integration:

  • stable request entry through HTTP Listener
  • extension-friendly transform dispatch via invokeDtsTransform
  • runtime pluggability through SPI + services/TransformDS
  • reusable mapping rules through DataSonnet import

This pattern is a strong baseline when teams need both fast transform delivery and controlled extension governance.

Links