Skip to content

Releases: Cumulocity-IoT/cumulocity-dynamic-mapper

Release 6.4.4-pre3

Release 6.4.4-pre3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 21 Aug 15:14
v6.4.4-pre3

spring boot 4.0, fixes ai-prompt, fix message explorer, bundled conne…

Release 6.4.4-pre2

Release 6.4.4-pre2 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 18 Aug 08:56

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.
  • 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 draft badge 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.
  • 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.

🐛 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: repeated 404s from the notification
      subscription API, or 422 Source object does not exist in inventory from
      measurement/event creation, with the device never recreated even though
      createNonExistingDevice was enabled.
    • Root cause: TenantRegistry's external-ID resolution cache had no invalidation path —
      a removeFromExternalIdCache method 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 to UPDATE events, silently dropping DELETE (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.0 DELETE event (now handled, with the
      now-pointless subscription torn down), and via the existing 422-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.

⚙️ 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.0 DELETE handling.
    • New shell integration test
      (test-inbound-implicit-device-recreate-after-delete.sh, registered in the inbound
      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.

Cumulocity Dynamic Mapper · v6.4.4 · August 2026
All releases on GitHub
Full Changelog: v6.4.3...develop

Release 6.4.4-pre1

Release 6.4.4-pre1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 13 Aug 14:02

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.

🐛 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: repeated 404s from the notification
      subscription API, or 422 Source object does not exist in inventory from
      measurement/event creation, with the device never recreated even though
      createNonExistingDevice was enabled.
    • Root cause: TenantRegistry's external-ID resolution cache had no invalidation path —
      a removeFromExternalIdCache method 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 to UPDATE events, silently dropping DELETE (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.0 DELETE event (now handled, with the
      now-pointless subscription torn down), and via the existing 422-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.

⚙️ 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.0 DELETE handling.
    • New shell integration test
      (test-inbound-implicit-device-recreate-after-delete.sh, registered in the inbound
      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.

Cumulocity Dynamic Mapper · v6.4.4 · August 2026
All releases on GitHub
Full Changelog: v6.4.3...develop

Release 6.4.3

Choose a tag to compare

@github-actions github-actions released this 12 Aug 13:21

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

  • explorerSessionTTLMinutes now 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 parentId limitation with autoCreateDeviceMO

    • Clarified in the Smart Function runtime type definitions that parentId is not yet honored when autoCreateDeviceMO creates a device — tracked further under #537.

🐛 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/# rejected fridgeNew/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.
  • 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 externalId is null/undefined #482

    • A JavaScript null/undefined externalId was 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.
  • 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 RepairStrategy handling

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

  • MappingTreeNode deletion 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.mappingNode and some dead code.
  • Reviewed and simplified the processor package

    • AbstractExtensibleResultProcessor, ExtensionResultProcessor, BaseProcessor/SendInboundProcessor, and DynamicMapperInboundRoutes were cleaned up; the now-unused ExecutionContext class was removed and its responsibilities folded into ProcessingContext.
    • The JSONata inbound/outbound processors (AbstractJSONataExtractionProcessor, JSONataInboundProcessor, JSONataOutboundProcessor) were reviewed and had significant duplicated logic consolidated.
    • Unused methods removed from SubstitutionContext and SubstitutionEvaluation.
  • Reviewed the mapping stepper and unified editor

    • MappingStepperService, MappingStepperComponent, and MappingUnifiedEditorComponent were simplified and had dead code removed.
  • Reviewed the subscription and substitution UI components

    • SubscriptionService, SubstitutionManagementService, MappingTransformationStepComponent, MappingStepperComponent, and TypeSelectorComponent were 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.
  • Migrated to Cumulocity 2026.43.0 (bootstrap 4.0.7) and updated the web SDK

    • Backend c8y.version raised to 2026.43.0, BootstrapService adjusted accordingly.
    • Frontend Cumulocity Web SDK dependencies updated (including vanilla-jsoneditor and related Angular/@c8y packages).

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

Pre-release

Choose a tag to compare

@github-actions github-actions released this 11 Aug 19:50

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

  • explorerSessionTTLMinutes now 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 parentId limitation with autoCreateDeviceMO

    • Clarified in the Smart Function runtime type definitions that parentId is not yet honored when autoCreateDeviceMO creates a device — tracked further under #537.

🐛 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/# rejected fridgeNew/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.
  • 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 externalId is null/undefined #482

    • A JavaScript null/undefined externalId was 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.
  • 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 RepairStrategy handling

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

  • MappingTreeNode deletion 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.mappingNode and some dead code.
  • Reviewed and simplified the processor package

    • AbstractExtensibleResultProcessor, ExtensionResultProcessor, BaseProcessor/SendInboundProcessor, and DynamicMapperInboundRoutes were cleaned up; the now-unused ExecutionContext class was removed and its responsibilities folded into ProcessingContext.
    • The JSONata inbound/outbound processors (AbstractJSONataExtractionProcessor, JSONataInboundProcessor, JSONataOutboundProcessor) were reviewed and had significant duplicated logic consolidated.
    • Unused methods removed from SubstitutionContext and SubstitutionEvaluation.
  • Reviewed the mapping stepper and unified editor

    • MappingStepperService, MappingStepperComponent, and MappingUnifiedEditorComponent were simplified and had dead code removed.
  • Reviewed the subscription and substitution UI components

    • SubscriptionService, SubstitutionManagementService, MappingTransformationStepComponent, MappingStepperComponent, and TypeSelectorComponent were 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.
  • Migrated to Cumulocity 2026.43.0 (bootstrap 4.0.7) and updated the web SDK

    • Backend c8y.version raised to 2026.43.0, BootstrapService adjusted accordingly.
    • Frontend Cumulocity Web SDK dependencies updated (including vanilla-jsoneditor and related Angular/@c8y packages).

Cumulocity Dynamic Mapper · v6.4.3 · August 2026
All releases on GitHub
Full Changelog: v6.4.2...develop

Release 6.4.2

Choose a tag to compare

@github-actions github-actions released this 17 Jul 08:21

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.
  • 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.js prebuild step), reducing the overall plugin size.
  • 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 code 1002, not 401, so the old disconnect handler never detected the unauthorized state and kept reusing an expired token indefinitely. Reconnect now also detects reason.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 marked RETRYING (new ConnectorStatus value) instead of FAILED, and initialization is retried with exponential backoff (10s initial, doubling, capped at 300s) until it succeeds or a non-retryable error occurs.
    • 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 AConnectorClient into 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.
  • AMQTTClient inconsistency #535

    • Fixed an inconsistency in AMQTTClient (Cumulocity MQTT Service connector) uncovered while hardening the connector lifecycle.
  • Race condition updating mapping statistics #536

    • Fixed a race condition when concurrently updating the message-count statistic on MappingStatus.

Cumulocity Dynamic Mapper · v6.4.2 · July 2026
All releases on GitHub
Full Changelog: v6.4.1...v6.4.2

Release 6.4.1

Choose a tag to compare

@github-actions github-actions released this 10 Jul 12:44
4ef927d

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

Choose a tag to compare

@github-actions github-actions released this 30 Jun 07:55
94f7e72

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 engineRotationThreshold context 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

Pre-release

Choose a tag to compare

@github-actions github-actions released this 22 Jun 07:18
new testcases

Release refs/tags/v6.4.0-pre2

Pre-release

Choose a tag to compare

@github-actions github-actions released this 18 Jun 11:27
v6.4.0-pre2