Releases: Cumulocity-IoT/cumulocity-dynamic-mapper
Release list
Release 6.4.4-pre3
v6.4.4-pre3 spring boot 4.0, fixes ai-prompt, fix message explorer, bundled conne…
Release 6.4.4-pre2
Release Notes — Cumulocity Dynamic Mapper v6.4.4
August 2026 · Dynamic Mapper
This release adds an AI-generated alternative to code templates when creating Smart
Functions, bundles a connector's connection-lifecycle status transitions into a single
event per connect/disconnect attempt instead of one independent event per status change,
and fixes a bug that left devices permanently unreachable — with repeated error-log
noise — once their auto-created device was deleted from inventory.
👤 Customer-Facing Changes
Changes that affect what users see or how the product behaves.
✨ New Features
-
Generate Smart Functions with AI instead of a code template #543
- When creating a new Inbound/Outbound mapping with transformation type Smart Function
(JavaScript), the "Select Payload Format and Transformation Type" step now offers an
explicit choice — "Choose Code Template" vs. "Generate with AI" — whenever an AI
agent is deployed for Smart Functions. The choice defaults to "Generate with AI" when an
agent is available, falling back to the template dropdown otherwise. - Generation is deferred until the Transformation step, where the real source/target
templates are available, and triggers automatically the first time that step is reached. - Fixed a related bug along the way: the auto-triggered generation could send a stale
default source template to the AI agent instead of the user's just-edited one, because it
relied on a change-event mirror that didn't fire for all edit paths (e.g. some tree-mode
interactions). It now reads the live content directly from the JSON editor.
- When creating a new Inbound/Outbound mapping with transformation type Smart Function
-
Open version history and see draft status directly from the Versions list #546
- The Monitoring → Versions pages (Versions inbound / Versions outbound) now have a
"Versions" row action that opens the existing version-history drawer for that mapping,
instead of requiring a detour through the main Mapping grid. - Added a "Status" column showing a
draftbadge for any mapping with unpublished draft
changes, so pending drafts are visible across the whole list at a glance instead of only
after opening each mapping individually.
- The Monitoring → Versions pages (Versions inbound / Versions outbound) now have a
-
Connector status log now shows one event per connect/disconnect attempt instead of one per status change #547
- Every connector status transition (
CONNECTING,CONNECTED,DISCONNECTING,
DISCONNECTED,RETRYING,FAILED) used to be posted as an independent Cumulocity
event, so a single connect attempt with one retry produced 3–4 unrelated rows in
Monitoring → Service events and the per-connector Details & logs page, with no
way to tell which rows belonged together. Each connection-lifecycle session is now
bundled into a single event that's updated in place as it progresses — the same
"History of changes" pattern Cumulocity Operations use — with an entry-count badge, an
"open"/error indicator, and an expandable compact timeline of that session's
transitions. CONFIGURED(a settle/idle marker, never itself part of a connect/disconnect attempt)
no longer generates its own event at all — it was showing up as an extra, low-signal
bundle on every disconnect/reconnect cycle. The connector's live status display is
unaffected; only the persisted event history changed.- Fixed a related bug found while verifying this in production: the MQTT and AMQP
connectors could report the same physical disconnect twice — once via the explicit
disconnect call, once via the underlying client library's own disconnected/exception
listener firing as a side effect of that same call — which showed up as two separate
sessions instead of one. Every other connector type (Kafka, Pulsar, HTTP, WebHook) was
checked and found not to have this pattern.
- Every connector status transition (
🐛 Bug Fixes
- Deleted devices left the mapper permanently unable to re-create them #544
- Once a device that the mapper had created implicitly (
createNonExistingDevice: true)
was later deleted from Cumulocity inventory, every subsequent inbound message for the
same external ID kept resolving to the deleted device's stale internal id — forever. This
produced a permanent per-message failure loop: repeated404s from the notification
subscription API, or422 Source object does not exist in inventoryfrom
measurement/event creation, with the device never recreated even though
createNonExistingDevicewas enabled. - Root cause:
TenantRegistry's external-ID resolution cache had no invalidation path —
aremoveFromExternalIdCachemethod existed for exactly this purpose but had never
been wired up to any actual failure path. The mapper's Notification 2.0 stream also
didn't help: it only reacted toUPDATEevents, silently droppingDELETE(and
CREATE) notifications without evicting anything. - Fixed by evicting the stale cache entry as soon as a deletion is discovered — via a real
inventory lookup, via a Notification 2.0DELETEevent (now handled, with the
now-pointless subscription torn down), and via the existing422-retry path in the
inbound message pipeline (which previously cleared a different, unrelated cache). A
message for a deleted device's external ID still hits one failure to discover the
deletion — unavoidable, that's how it's detected — but the very next message now gets a
freshly created device instead of repeating the same failure indefinitely. - Also cleaned up related error-log noise: the same failure was previously logged three
times, with a full stack trace each time, as it propagated up through nested handlers
that just rethrew it unchanged. Now logged once, at the point where it's actually
handled.
- Once a device that the mapper had created implicitly (
⚙️ Internal / Implementation Changes
Refactoring, code-quality, and platform maintenance work with no intended change in
customer-visible behavior.
- Added regression coverage for the device-recreation fix #544
- New unit tests for
TenantRegistry's external-ID cache reverse-index/eviction, for
InventoryCacheEnrichmentService's device-not-found path, and for
CacheInventoryUpdateClient's Notification 2.0DELETEhandling. - New shell integration test
(test-inbound-implicit-device-recreate-after-delete.sh, registered in theinbound
suite): create an implicit device, delete it, resend a message for the same external ID,
and assert a new device is auto-created with a different internal id.
- New unit tests for
Cumulocity Dynamic Mapper · v6.4.4 · August 2026
All releases on GitHub
Full Changelog: v6.4.3...develop
Release 6.4.4-pre1
Release Notes — Cumulocity Dynamic Mapper v6.4.4
August 2026 · Dynamic Mapper Service
This release adds an AI-generated alternative to code templates when creating Smart
Functions, and fixes a bug that left devices permanently unreachable — with repeated
error-log noise — once their auto-created device was deleted from inventory.
👤 Customer-Facing Changes
Changes that affect what users see or how the product behaves.
✨ New Features
- Generate Smart Functions with AI instead of a code template #543
- When creating a new Inbound/Outbound mapping with transformation type Smart Function
(JavaScript), the "Select Payload Format and Transformation Type" step now offers an
explicit choice — "Choose Code Template" vs. "Generate with AI" — whenever an AI
agent is deployed for Smart Functions. The choice defaults to "Generate with AI" when an
agent is available, falling back to the template dropdown otherwise. - Generation is deferred until the Transformation step, where the real source/target
templates are available, and triggers automatically the first time that step is reached. - Fixed a related bug along the way: the auto-triggered generation could send a stale
default source template to the AI agent instead of the user's just-edited one, because it
relied on a change-event mirror that didn't fire for all edit paths (e.g. some tree-mode
interactions). It now reads the live content directly from the JSON editor.
- When creating a new Inbound/Outbound mapping with transformation type Smart Function
🐛 Bug Fixes
- Deleted devices left the mapper permanently unable to re-create them #544
- Once a device that the mapper had created implicitly (
createNonExistingDevice: true)
was later deleted from Cumulocity inventory, every subsequent inbound message for the
same external ID kept resolving to the deleted device's stale internal id — forever. This
produced a permanent per-message failure loop: repeated404s from the notification
subscription API, or422 Source object does not exist in inventoryfrom
measurement/event creation, with the device never recreated even though
createNonExistingDevicewas enabled. - Root cause:
TenantRegistry's external-ID resolution cache had no invalidation path —
aremoveFromExternalIdCachemethod existed for exactly this purpose but had never
been wired up to any actual failure path. The mapper's Notification 2.0 stream also
didn't help: it only reacted toUPDATEevents, silently droppingDELETE(and
CREATE) notifications without evicting anything. - Fixed by evicting the stale cache entry as soon as a deletion is discovered — via a real
inventory lookup, via a Notification 2.0DELETEevent (now handled, with the
now-pointless subscription torn down), and via the existing422-retry path in the
inbound message pipeline (which previously cleared a different, unrelated cache). A
message for a deleted device's external ID still hits one failure to discover the
deletion — unavoidable, that's how it's detected — but the very next message now gets a
freshly created device instead of repeating the same failure indefinitely. - Also cleaned up related error-log noise: the same failure was previously logged three
times, with a full stack trace each time, as it propagated up through nested handlers
that just rethrew it unchanged. Now logged once, at the point where it's actually
handled.
- Once a device that the mapper had created implicitly (
⚙️ Internal / Implementation Changes
Refactoring, code-quality, and platform maintenance work with no intended change in
customer-visible behavior.
- Added regression coverage for the device-recreation fix #544
- New unit tests for
TenantRegistry's external-ID cache reverse-index/eviction, for
InventoryCacheEnrichmentService's device-not-found path, and for
CacheInventoryUpdateClient's Notification 2.0DELETEhandling. - New shell integration test
(test-inbound-implicit-device-recreate-after-delete.sh, registered in theinbound
suite): create an implicit device, delete it, resend a message for the same external ID,
and assert a new device is auto-created with a different internal id.
- New unit tests for
Cumulocity Dynamic Mapper · v6.4.4 · August 2026
All releases on GitHub
Full Changelog: v6.4.3...develop
Release 6.4.3
Release Notes — Cumulocity Dynamic Mapper 6.4.3
August 2026 · Dynamic Mapper
This release reworks the AI Assistant's review-vs-generate flow, fixes a class of MQTT
wildcard-topic validation bugs, and includes a broader internal code review pass across
the processor, stepper, and subscription/substitution code paths, plus platform SDK
updates and a documentation format migration.
👤 Customer-Facing Changes
Changes that affect what users see or how the product behaves.
✨ New Features
- Inline suggestion chips replace the full-screen review/generate choice #541
- Opening the AI Assistant for a mapping that already has a Smart Function or substitutions used to show a separate, blocking full-screen choice ("What would you like to do?") before any chat was visible.
- Replaced with small clickable suggestion chips ("Review / Refine existing…" / "Generate new… from scratch") rendered inline in the chat itself, so the chat is visible immediately and the user picks intent from within it.
- Brand-new mappings (nothing to review yet, e.g. created from Message Explorer or "+Add mapping") are unaffected — generation still starts immediately with no user interaction.
- The welcome area also now explains what each choice does, instead of showing just a bare headline/title.
🔧 Improvements
-
explorerSessionTTLMinutesnow configurable- The Message Explorer session TTL is now exposed as a setting in the service configuration UI, instead of being hardcoded in the backend.
-
Removed the "session started" toast in Message Explorer
- Starting a new Message Explorer session no longer pops up a success toast; the "session stopped"/"session updated"/"session expired" notifications are unchanged.
-
Documented
parentIdlimitation withautoCreateDeviceMO- Clarified in the Smart Function runtime type definitions that
parentIdis not yet honored whenautoCreateDeviceMOcreates a device — tracked further under #537.
- Clarified in the Smart Function runtime type definitions that
🐛 Bug Fixes
-
Mapping topic
#wildcard validation incorrectly rejected valid MQTT topic samples #538- The mapping topic and topic-sample were compared for exact segment-count equality before ever applying
#-wildcard semantics, so a trailing#only matched when the sample happened to have the same number of levels as the topic pattern — e.g.fridgeNew/#rejectedfridgeNew/east/sensor-ny-99, blocking the mapping wizard's "Next" button. - Per MQTT semantics, a trailing
#now correctly matches any number (including zero) of remaining levels.
- The mapping topic and topic-sample were compared for exact segment-count equality before ever applying
-
AI Assistant silently dropped the first message when generating a brand-new Smart Function #540
- The very first AI generation prompt for a new mapping was silently dropped with no visible error, due to an Angular component-lifecycle timing issue. Fixed so generation now reliably starts.
-
Don't implicitly create devices when a Smart Function's
externalIdisnull/undefined#482- A JavaScript
null/undefinedexternalIdwas silently coerced into the literal strings"null"/"undefined", which then passed downstream device-resolution checks and triggered implicit device creation for devices that were never meant to exist.
- A JavaScript
-
Fixed JSON ↔ Map parsing for Smart Functions
- Fixed a round-tripping bug converting between JSON and the Smart Function runtime's internal Map representation, which could produce incorrect payload data in some Smart Functions.
-
Fixed inconsistencies in
RepairStrategyhandling- Substitution repair strategies were not always applied consistently between JSONata processing and the edit-substitution UI; behavior is now consistent, and the JSONata documentation page now documents the available strategies.
⚙️ Internal / Implementation Changes
Refactoring, code-quality, and platform maintenance work with no intended change in
customer-visible behavior.
-
MappingTreeNodedeletion scanned every sibling branch instead of the matching topic level #539- Deleting a mapping scanned all sibling branches at the same tree depth to find the node to remove, instead of scoping to the matching topic level like the equivalent inner-node deletion path already did. Only mapping-ID uniqueness prevented this from ever producing an observable bug, but it was the wrong operation regardless. Also removed a latent NPE risk on
MappingTreeNode.mappingNodeand some dead code.
- Deleting a mapping scanned all sibling branches at the same tree depth to find the node to remove, instead of scoping to the matching topic level like the equivalent inner-node deletion path already did. Only mapping-ID uniqueness prevented this from ever producing an observable bug, but it was the wrong operation regardless. Also removed a latent NPE risk on
-
Reviewed and simplified the processor package
AbstractExtensibleResultProcessor,ExtensionResultProcessor,BaseProcessor/SendInboundProcessor, andDynamicMapperInboundRouteswere cleaned up; the now-unusedExecutionContextclass was removed and its responsibilities folded intoProcessingContext.- The JSONata inbound/outbound processors (
AbstractJSONataExtractionProcessor,JSONataInboundProcessor,JSONataOutboundProcessor) were reviewed and had significant duplicated logic consolidated. - Unused methods removed from
SubstitutionContextandSubstitutionEvaluation.
-
Reviewed the mapping stepper and unified editor
MappingStepperService,MappingStepperComponent, andMappingUnifiedEditorComponentwere simplified and had dead code removed.
-
Reviewed the subscription and substitution UI components
SubscriptionService,SubstitutionManagementService,MappingTransformationStepComponent,MappingStepperComponent, andTypeSelectorComponentwere cleaned up, with a large amount of now-unused subscription-handling code removed.
-
Documentation migrated to Markdown
- The plugin's in-app documentation (overview, JSONata reference) was converted from its previous format to Markdown, split into
overview-part1.md/overview-part2.md, matching the rest of the docs.
- The plugin's in-app documentation (overview, JSONata reference) was converted from its previous format to Markdown, split into
-
Migrated to Cumulocity 2026.43.0 (bootstrap 4.0.7) and updated the web SDK
- Backend
c8y.versionraised to2026.43.0,BootstrapServiceadjusted accordingly. - Frontend Cumulocity Web SDK dependencies updated (including
vanilla-jsoneditorand related Angular/@c8ypackages).
- Backend
Cumulocity Dynamic Mapper · v6.4.3 · August 2026
All releases on GitHub
Full Changelog: v6.4.2...develop
Release refs/tags/v6.4.3-pre3
Release Notes — Cumulocity Dynamic Mapper v6.4.3-pre3
August 2026 · Dynamic Mapper Service
This release reworks the AI Assistant's review-vs-generate flow, fixes a class of MQTT
wildcard-topic validation bugs, and includes a broader internal code review pass across
the processor, stepper, and subscription/substitution code paths, plus platform SDK
updates and a documentation format migration.
👤 Customer-Facing Changes
Changes that affect what users see or how the product behaves.
✨ New Features
- Inline suggestion chips replace the full-screen review/generate choice #541
- Opening the AI Assistant for a mapping that already has a Smart Function or substitutions used to show a separate, blocking full-screen choice ("What would you like to do?") before any chat was visible.
- Replaced with small clickable suggestion chips ("Review / Refine existing…" / "Generate new… from scratch") rendered inline in the chat itself, so the chat is visible immediately and the user picks intent from within it.
- Brand-new mappings (nothing to review yet, e.g. created from Message Explorer or "+Add mapping") are unaffected — generation still starts immediately with no user interaction.
- The welcome area also now explains what each choice does, instead of showing just a bare headline/title.
🔧 Improvements
-
explorerSessionTTLMinutesnow configurable- The Message Explorer session TTL is now exposed as a setting in the service configuration UI, instead of being hardcoded in the backend.
-
Removed the "session started" toast in Message Explorer
- Starting a new Message Explorer session no longer pops up a success toast; the "session stopped"/"session updated"/"session expired" notifications are unchanged.
-
Documented
parentIdlimitation withautoCreateDeviceMO- Clarified in the Smart Function runtime type definitions that
parentIdis not yet honored whenautoCreateDeviceMOcreates a device — tracked further under #537.
- Clarified in the Smart Function runtime type definitions that
🐛 Bug Fixes
-
Mapping topic
#wildcard validation incorrectly rejected valid MQTT topic samples #538- The mapping topic and topic-sample were compared for exact segment-count equality before ever applying
#-wildcard semantics, so a trailing#only matched when the sample happened to have the same number of levels as the topic pattern — e.g.fridgeNew/#rejectedfridgeNew/east/sensor-ny-99, blocking the mapping wizard's "Next" button. - Per MQTT semantics, a trailing
#now correctly matches any number (including zero) of remaining levels.
- The mapping topic and topic-sample were compared for exact segment-count equality before ever applying
-
AI Assistant silently dropped the first message when generating a brand-new Smart Function #540
- The very first AI generation prompt for a new mapping was silently dropped with no visible error, due to an Angular component-lifecycle timing issue. Fixed so generation now reliably starts.
-
Don't implicitly create devices when a Smart Function's
externalIdisnull/undefined#482- A JavaScript
null/undefinedexternalIdwas silently coerced into the literal strings"null"/"undefined", which then passed downstream device-resolution checks and triggered implicit device creation for devices that were never meant to exist.
- A JavaScript
-
Fixed JSON ↔ Map parsing for Smart Functions
- Fixed a round-tripping bug converting between JSON and the Smart Function runtime's internal Map representation, which could produce incorrect payload data in some Smart Functions.
-
Fixed inconsistencies in
RepairStrategyhandling- Substitution repair strategies were not always applied consistently between JSONata processing and the edit-substitution UI; behavior is now consistent, and the JSONata documentation page now documents the available strategies.
⚙️ Internal / Implementation Changes
Refactoring, code-quality, and platform maintenance work with no intended change in
customer-visible behavior.
-
MappingTreeNodedeletion scanned every sibling branch instead of the matching topic level #539- Deleting a mapping scanned all sibling branches at the same tree depth to find the node to remove, instead of scoping to the matching topic level like the equivalent inner-node deletion path already did. Only mapping-ID uniqueness prevented this from ever producing an observable bug, but it was the wrong operation regardless. Also removed a latent NPE risk on
MappingTreeNode.mappingNodeand some dead code.
- Deleting a mapping scanned all sibling branches at the same tree depth to find the node to remove, instead of scoping to the matching topic level like the equivalent inner-node deletion path already did. Only mapping-ID uniqueness prevented this from ever producing an observable bug, but it was the wrong operation regardless. Also removed a latent NPE risk on
-
Reviewed and simplified the processor package
AbstractExtensibleResultProcessor,ExtensionResultProcessor,BaseProcessor/SendInboundProcessor, andDynamicMapperInboundRouteswere cleaned up; the now-unusedExecutionContextclass was removed and its responsibilities folded intoProcessingContext.- The JSONata inbound/outbound processors (
AbstractJSONataExtractionProcessor,JSONataInboundProcessor,JSONataOutboundProcessor) were reviewed and had significant duplicated logic consolidated. - Unused methods removed from
SubstitutionContextandSubstitutionEvaluation.
-
Reviewed the mapping stepper and unified editor
MappingStepperService,MappingStepperComponent, andMappingUnifiedEditorComponentwere simplified and had dead code removed.
-
Reviewed the subscription and substitution UI components
SubscriptionService,SubstitutionManagementService,MappingTransformationStepComponent,MappingStepperComponent, andTypeSelectorComponentwere cleaned up, with a large amount of now-unused subscription-handling code removed.
-
Documentation migrated to Markdown
- The plugin's in-app documentation (overview, JSONata reference) was converted from its previous format to Markdown, split into
overview-part1.md/overview-part2.md, matching the rest of the docs.
- The plugin's in-app documentation (overview, JSONata reference) was converted from its previous format to Markdown, split into
-
Migrated to Cumulocity 2026.43.0 (bootstrap 4.0.7) and updated the web SDK
- Backend
c8y.versionraised to2026.43.0,BootstrapServiceadjusted accordingly. - Frontend Cumulocity Web SDK dependencies updated (including
vanilla-jsoneditorand related Angular/@c8ypackages).
- Backend
Cumulocity Dynamic Mapper · v6.4.3 · August 2026
All releases on GitHub
Full Changelog: v6.4.2...develop
Release 6.4.2
Release Notes — Cumulocity Dynamic Mapper v6.4.2
July 2026 · Dynamic Mapper Service
This release focuses on connector resilience: the Dynamic Mapper now recovers cleanly
from temporary Cumulocity backend outages instead of getting stuck in a failed or
partially-functional state. It also adds backfill for outbound type subscriptions,
a faster/smaller web app bundle, visible AI token usage, and server-side search for
subscriptions.
✨ New Features
-
Backfill existing devices into outbound type subscriptions #526
- Outbound subscriptions scoped to a device type previously only applied to devices created after the subscription was set up.
- A new resync action backfills already-existing devices of that type into the subscription, triggered on demand from the subscription UI and processed as a background job with progress reported via logging events.
-
Server-side search for subscriptions #532
- Searching for devices in the outbound subscription view is now performed server-side via a new
SubscriptionQueryService, with wildcard support added shortly after. - Previously search was limited to whatever was loaded client-side, so large device populations were only partially searchable.
- Searching for devices in the outbound subscription view is now performed server-side via a new
-
Token usage shown in AI-prompt #533
- The AI-prompt panel used to auto-generate Smart Functions now displays token usage for the request, giving visibility into cost/consumption per generation.
🔧 Improvements
-
Smaller web app bundle #534
- Images bundled with the web app plugin are now optimized as part of the build (
optimize-images.jsprebuild step), reducing the overall plugin size.
- Images bundled with the web app plugin are now optimized as part of the build (
-
Quieter logging during backend outages
- When the Cumulocity platform is temporarily unavailable, the service now avoids logging the full stack trace for the resulting errors, cutting down log noise during an already-noisy incident.
🐛 Bug Fixes
-
Connector reconnect & lifecycle fixes after temporary backend unavailability #530
- Fixes a class of failures where, after a brief Cumulocity platform outage or gateway hiccup, a connector's underlying transport (e.g. MQTT) recovered but the Dynamic Mapper itself remained stuck or only partially functional:
- 401 WebSocket reconnect loop. The management/cache-inventory notification WebSockets (
ManagementSubscriptionClient,CacheInventoryUpdateClient) failed their reconnect handshake as unauthorized on every attempt. The underlying WebSocket library reports a rejected upgrade as close code1002, not401, so the old disconnect handler never detected the unauthorized state and kept reusing an expired token indefinitely. Reconnect now also detectsreason.contains("401")and prefers a stored/refreshed token before minting a new one. - 502/503/504 during subscription initialization. After reconnect, the Dynamic Mapper rebuilds its mapping/subscription caches via a Cumulocity Inventory API call that can transiently return
502 Bad Gateway(or 503/504) during a brief outage. This previously aborted subscription initialization entirely with no retry, even though the connector transport was healthy. Retryable status codes are now detected, the connector is markedRETRYING(newConnectorStatusvalue) instead ofFAILED, and initialization is retried with exponential backoff (10s initial, doubling, capped at 300s) until it succeeds or a non-retryable error occurs.
- 401 WebSocket reconnect loop. The management/cache-inventory notification WebSockets (
- The underlying lifecycle/concurrency fixes were then rolled out consistently across all broker connectors (AMQP 1.0, AMQP, HTTP, Kafka, MQTT v3/v5, Cumulocity MQTT Service/Pulsar), and SSL support plus explorer-listener handling were extracted out of
AConnectorClientinto dedicated classes (ConnectorSslSupport,ExplorerListenerRegistry) to make that logic easier to test and reuse. - A new integration test setup and fault-injection script (
resources/script/backend/TEST-SETUP-C8Y-UNAVAILABLE.md,resources/script/backend/fault_inject.py) reproduce both failure modes for verification.
- Fixes a class of failures where, after a brief Cumulocity platform outage or gateway hiccup, a connector's underlying transport (e.g. MQTT) recovered but the Dynamic Mapper itself remained stuck or only partially functional:
-
AMQTTClient inconsistency #535
- Fixed an inconsistency in
AMQTTClient(Cumulocity MQTT Service connector) uncovered while hardening the connector lifecycle.
- Fixed an inconsistency in
-
Race condition updating mapping statistics #536
- Fixed a race condition when concurrently updating the message-count statistic on
MappingStatus.
- Fixed a race condition when concurrently updating the message-count statistic on
Cumulocity Dynamic Mapper · v6.4.2 · July 2026
All releases on GitHub
Full Changelog: v6.4.1...v6.4.2
Release 6.4.1
What's Changed
- Fixing a bug that leads to WebSocket could not reconnect with 401 #528
- Making MQTT Reconnect more robust in cases where C8Y returns 5xx error codes #527
- Improved logging
Full Changelog: v6.4.0...v6.4.1
Release v6.4.0
Release Notes — Cumulocity Dynamic Mapper v6.4.0
This release introduces mapping versioning, automatic GraalVM JS engine rotation,
and a comprehensive end-to-end test suite. Snooping has been removed.
Several long-standing bug fixes ship alongside internal architectural improvements.
⚠️ Breaking Changes
Snooping removed #523
The snooping feature — which sampled live broker traffic to discover message payload
schemas — has been fully removed from the backend and UI after some deprecation
period; the feature is gone in this release. It is replaced by the already introduced Message Explorer,
which provides live message inspection with session-scoped filtering and a configurable TTL.
✨ New Features
Mapping versioning #524
Mappings now maintain a full version history. Each saved mapping creates an immutable
version following the SemVer schema; a configurable maximum version count controls how many are retained. A draft
workflow lets you stage changes before committing them. Previous versions can be browsed,
and restored directly from the mapping editor.
GraalVM JS engine rotation
The GraalVM polyglot engine used to execute Smart Functions is now automatically rotated
to prevent unbounded memory growth. Two strategies run in parallel:
- Count-based rotation — after
engineRotationThresholdcontext creations (default: 100) - Time-based rotation — after
engineMaxAgeMinutes(default: off)
Both thresholds are configurable in the service configuration page. A manual
Rotate engines action is also available from the service configuration UI for
on-demand reclamation.
Message Explorer — Session TTL #521
The WebSocket session time-to-live (in minutes) is now configurable directly from the
Message Explorer UI. Previously this required a backend service configuration change
and a restart.
Comprehensive end-to-end test suite
A new bash-based integration test suite ships under resources/script/test/. It covers
40+ inbound and outbound scenarios: JSON, JSONata, Smart Functions, extensions (SparkPlugB,
FlatFile, Hex), multi-device, multi-connector, multi-tenant, reconnect, static subscriptions,
group subscriptions, and more.
A shared test harness (test-harness.sh) lets the same scripts run against the public
MQTT broker or the Cumulocity MQTT Service (X.509 certificate auth) with no per-file
changes.
# Run all tests
bash run-tests.sh
# Run inbound suite against the Cumulocity MQTT Service
bash run-tests.sh inbound m
# Run everything against the public broker
bash run-tests.sh all g🔧 Improvements
Smart Function pipeline timeout & cancellation
Smart Function execution now supports a configurable pipeline timeout via
pipelineTimeoutMS. When the timeout is exceeded, a cancellation signal is sent to the
C8Y agent, stopping in-flight processing and releasing resources cleanly.
Outbound soft-skip for missing external ID
When an outbound mapping targets a device that has no registered external ID, the
pipeline now performs a soft skip — logging a warning and continuing — rather than a
hard abort that could affect unrelated mappings in the same pipeline.
Spring AI upgraded to 2.0.0
The AI agent integration used for auto-generating mappings has been upgraded to
Spring AI 2.0.0. MCP server issues from prior releases are resolved in this upgrade.
🐛 Bug Fixes
Smart Functions: missing atob / btoa
The standard base64 functions atob and btoa were unavailable inside the GraalVM
Smart Function sandbox, causing runtime errors for mappings that performed base64
encoding or decoding. Both functions are now present in the sandbox environment.
Duplicate message processing
Fixed a bug where the same inbound message could be processed and forwarded to
Cumulocity more than once, resulting in duplicate measurements, events, or alarms.
Smart Function warm-up IIFE isolation
warmupMappingCodes now wraps each mapping's JavaScript in the same
immediately-invoked function expression (IIFE) that the runtime uses during normal
execution. Previously, bare code evaluated at warm-up could leak variables across
mappings and cause non-deterministic failures at engine startup.
Target template not updating on mapping edit
Fixed a bug where changes to the targetTemplate field were silently discarded when
saving an existing mapping, leaving the old template active.
Mapping version display in editor
Resolved several related UI issues: the editor showed the wrong version number after a
draft was deleted; the version dialog displayed stale data after a save; and the version
label showed an incorrect value in the unified editor when switching between mappings.
Draft save guard
The mapping editor save button is now disabled when required fields are missing or
invalid, preventing incomplete drafts from being persisted to the backend.
Stale MQTT push connections cleaned up on timeout #525
When a device's MQTT push connection timed out, the dead client entry was left in the
internal connection map. This blocked future reconnection attempts for the same device
and produced repeated WARN log messages. The entry is now evicted atomically on timeout,
and the log level for expected timeouts (e.g. test devices cleaned up at test end) has
been lowered from WARN to DEBUG.
🏗 Internal & Technical
C8YAgent decomposed into focused service classes
The monolithic C8YAgent class has been split into purpose-specific services
(inventory, identity, events, measurements, alarms, operations). This makes unit
testing easier and removes hidden cross-concern dependencies.
Constructor injection throughout the service
Spring @Autowired field injection has been replaced with constructor injection across
the service layer. This resolves several circular dependency issues and makes the
dependency graph explicit and verifiable at compile time.
Typed Apache Camel header constants
Raw string keys for Apache Camel message headers have been replaced with typed
constants, eliminating a class of silent routing bugs caused by header name typos.
Deprecated MQTTServiceClient removed
The deprecated MQTTServiceClient class has been removed. All MQTT Service
interactions now go through the unified connector path (CUMULOCITY_MQTT_SERVICE_PULSAR).
Cumulocity Dynamic Mapper · v6.4.0 · June 2026
All releases on GitHub
Full Changelog: v6.3.4...v6.4.0
Release refs/tags/v6.4.0-pre3
new testcases
Release refs/tags/v6.4.0-pre2
v6.4.0-pre2