Skip to content

Starter export/import omits Experiments and Variants data #36337

Description

@erickgonzalez

Problem Statement

The maintenance starter export endpoints do not include Experiments or their Variants, and the import path does not restore them. As a result, a starter generated for backup or migration silently loses all A/B testing experiment data.

Affected endpoints:

  • GET /api/v1/maintenance/_downloadStarterWithAssets
  • GET /api/v1/maintenance/_downloadStarter

Root cause: ExportStarterUtil only exports (a) Hibernate-mapped entities plus a small hardcoded list (getTableSet()), and (b) a few hand-coded non-Hibernate "special" tables — Counter, Image, Portlet, Workflows, Rules (getAdditionalDataAsJSON()). The experiment table is persisted via DotConnect (not Hibernate) and is in neither list, so it is never written to the starter. The same applies to the variant table, which holds the experiment-variant rows (dotexperiment-<id>-variant-<n>) that the already-exported variant content (contentlet_version_info / multi_tree) references — without those rows, restored experiments resolve to orphaned variants.

Impact / scope:

  • Affects starter-based backup and instance-to-instance migration.
  • Particularly serious on MSSQL or any environment where the pg_dump binary is unavailable, because the JSON starter is then the only backup path. (The separate pg_dump path — _pgDumpAvailable / _downloadDb — already includes experiment/variant since they are not in its --exclude-table-data deny-list, so that path is not affected.)

Steps to Reproduce

  1. On a dotCMS instance, create an A/B testing Experiment on a page (this writes a row to the experiment table and dotexperiment-… rows to the variant table).
  2. Call GET /api/v1/maintenance/_downloadStarterWithAssets (or _downloadStarter) as an admin.
  3. Unzip the downloaded starter and inspect the JSON entries.

Expected: The ZIP contains the experiment data (e.g. Experiment.json) and the variant rows (e.g. Variant.json), and importing the starter into a clean instance restores the experiment and its variants.

Actual: No experiment or variant data is present in the ZIP. After importing such a starter, the experiment and its variants do not exist on the target instance.

Acceptance Criteria

  • GET /api/v1/maintenance/_downloadStarter and _downloadStarterWithAssets both include the experiment table data in the generated starter.
  • Both endpoints include the variant table data (all rows, including archived and DEFAULT).
  • Importing a starter restores experiments via ImportStarterUtil, preserving the experiment id and JSONB fields (traffic_proportion, scheduling, goals, running_ids).
  • Importing restores variant rows, skipping the always-present DEFAULT variant and not failing on archived experiment variants.
  • Import ordering is correct: variants are imported before contentlet version info / multi-tree; experiments are imported after contentlets (experiment page_id references a contentlet identifier).
  • Round-trip (export → import into a clean instance) results in the experiment opening correctly in the UI with its variants intact.
  • Works on both PostgreSQL and MSSQL (JSONB vs NVARCHAR handling via existing DotConnect.addJSONParam).
  • The pg_dump path (_downloadDb) remains unchanged.

dotCMS Version

Latest from main branch.

Links

NA

Metadata

Metadata

Assignees

No one assigned

    Type

    Fields

    No fields configured for Bug.

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions