Skip to content
    All posts
    Oracle WebCenter ContentFusion Middleware14c UpgradeMigrationUCM

    Cloning an Oracle WebCenter Content instance for a safe test upgrade

    July 10, 202610 min readBy Andrew Blackman

    If you're planning an Oracle WebCenter Content (WCC / UCM) upgrade — and if you're on 12c watching the December 2026 Premier Support date approach, you are — the single most valuable thing you can do before touching production is rehearse the whole upgrade on a true copy of your instance. Not a sampled subset. Not a fresh install with a handful of test documents. A clone that carries your real content, your real metadata schema, your real folders and workflows, so that when the upgrade throws an error, it throws your error, on your data — while production sits untouched.

    I've built these clones as the first step of real WCC upgrade projects, and the reason it matters is simple: WebCenter Content is three things bolted together — a content repository on the filesystem (the vault and weblayout directories), a metadata schema in the database (revisions, documents, docmeta, and dozens of supporting tables), and the application that indexes and serves it. A test upgrade is only trustworthy if all three come along. Miss one and you're rehearsing against a fiction.

    Here's the field runbook for standing that clone up.

    The shape of the problem

    A WCC instance you can trust as a rehearsal target has to reproduce three layers:

    1. The database schema — the OCS tables that hold every content item's revision history, metadata, workflow state, folder structure, and users.
    2. The filesystem — the vault (native files) and weblayout (rendered/web-viewable copies) directories that the database rows point at.
    3. The internal counters — the database sequences that hand out the next document ID, revision ID, and revision-class ID. Get these wrong and the first thing a user does on the clone corrupts it.

    The approach below moves content-bearing data from a cloned copy of production into a freshly provisioned target-version schema, over a database link, table by table. Working table-by-table (rather than a blind full-schema import) is deliberate: it lets you filter out system content, reconcile schema differences between your source and target releases, and understand what you're carrying — which is exactly the understanding you'll need again when you run the real upgrade.

    The single judgment call underneath everything below is one a runbook can't make for you: which of your tables are content-bearing customer data and which are machinery the fresh target already owns. That line moves with every custom component, every profile, and every integration your estate has accumulated. Get it wrong in one direction and you drag internal system rows on top of the ones the fresh instance created — a silent duplication you won't see until something behaves oddly. Get it wrong in the other and you leave a supporting table behind and the clone renders content that has no workflow, no profile, or no security behind it. The steps are mechanical; deciding where that line falls for your estate is the part that isn't.

    Step 1: link the two databases

    Everything downstream runs over a database link from the target (new-version) schema to the cloned-production schema:

    CREATE DATABASE LINK DBLINK_WCC_PROD_CLONED
      CONNECT TO STG_OCS IDENTIFIED BY ********
      USING '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<cloned-db-host>)(PORT=1521))
              (CONNECT_DATA=(SERVICE_NAME=<cloned-service>)))';
    

    Point it at a clone of production, not production itself. The whole exercise is about not touching the live system — and a long-running insert ... select pulling millions of rows across a link into production would defeat the purpose.

    Step 2: copy the content tables, filtering system content

    The core content lives in a small set of related tables. Copy them in dependency order, and filter out System document types — you want the customer's content, not the internal machinery, which the fresh target instance already has its own copy of:

    -- Revisions: the master list of every content item version
    insert into TARGET_OCS.revisions
      select * from revisions@DBLINK_WCC_PROD_CLONED
      where ddoctype <> 'System';
    
    -- Revclasses: revision-class rows for those items
    insert into TARGET_OCS.revclasses
      select * from revclasses@DBLINK_WCC_PROD_CLONED
      where ddocname in (
        select ddocname from revisions@DBLINK_WCC_PROD_CLONED
        where ddoctype <> 'System');
    
    -- Documents: the file-level rows tied to those revisions
    insert into TARGET_OCS.documents
      select * from documents@DBLINK_WCC_PROD_CLONED
      where did in (
        select did from revisions@DBLINK_WCC_PROD_CLONED
        where ddoctype <> 'System');
    

    Then documenthistory, which needs the same did-based filtering. Before you copy it, count on both sides and reconcile — history rows can reference IDs that fall outside your filtered revision set, and you want to decide consciously whether to carry them rather than discover the mismatch later:

    select count(*) from documenthistory@DBLINK_WCC_PROD_CLONED
      where did in (select did from revisions@DBLINK_WCC_PROD_CLONED
                    where ddoctype <> 'System');
    

    Step 3: reconcile the metadata table — docmeta is where clones bite

    docmeta holds every custom metadata field on your content — and in a real WCC estate that's not five columns, it's a hundred-plus x-prefixed fields (xComments, xKeywords, xProductCategory, and on and on). Two things bite here, and both are why a naive full-copy fails.

    First: column-width drift. Between releases, some metadata columns that were narrower in the source can need to be 4000 characters in the target — and if the target's column is shorter, the insert throws on the first over-length value. Find every wide column on the source, then widen its counterpart on the target before you copy:

    -- List the 4000-char columns on the source
    SELECT column_name, data_type, char_length
      FROM USER_TAB_COLUMNS@DBLINK_WCC_PROD_CLONED
      WHERE table_name = 'DOCMETA' and char_length = 4000;
    
    -- Widen each one on the target to match
    ALTER TABLE TARGET_OCS.docmeta MODIFY xComments      VARCHAR2(4000);
    ALTER TABLE TARGET_OCS.docmeta MODIFY xKeywords      VARCHAR2(4000);
    ALTER TABLE TARGET_OCS.docmeta MODIFY xProductCategory VARCHAR2(4000);
    -- ...one ALTER per wide column, then re-run the SELECT against the
    -- TARGET and confirm the count matches the source exactly.
    

    Second: columns that exist on one side and not the other. The target release can introduce metadata columns the source never had (things like a template-type or annotation-details field). You cannot insert ... select * across that gap — the column lists won't line up. You have to name every column explicitly on both sides, and supply a sensible default (NULL, or 0 for a boolean-style flag) for the new target-only columns:

    insert into TARGET_OCS.docmeta (xComments, xKeywords, /* ...all columns... */, xTemplateType, xIsAclReadOnlyOnUI, DID)
      select xComments, xKeywords, /* ...matching source columns... */, NULL, 0, DID
      from docmeta@DBLINK_WCC_PROD_CLONED
      where did in (select did from revisions@DBLINK_WCC_PROD_CLONED
                    where ddoctype <> 'System');
    

    This explicit column mapping is tedious, and it's exactly the tedium that makes the rehearsal worth it: you resolve every schema difference here, on the clone, instead of at 2am against production.

    Caution: the trap in this step is that a mis-mapped docmeta column doesn't error — it runs. Line up the source and target column lists in the wrong order, or default a new target-only column to the wrong value, and the insert succeeds and quietly writes the wrong metadata onto every row. The clone comes up, queries return counts that match, and a spot check on ten documents looks fine — because the corruption is uniform, not sparse. Whether a given new column should default to NULL, 0, or a real value is an estate-specific judgment about what that field means in your content model; there is no generic right answer, and the insert won't tell you that you chose wrong.

    Step 4: carry workflows, users, folders, and profiles

    Content without its surrounding state isn't a faithful rehearsal. Copy the supporting tables:

    • Workflow stateWorkflowDocuments, WorkflowDocAttributes, WorkflowHistory. Items mid-approval on production should be mid-approval on the clone.
    • Profile trigger valuesProfileTriggerValues, which drive content-profile behaviour.
    • Users and security attributesUsers and UserSecurityAttributes, excluding the platform accounts (weblogic, sysadmin) that the fresh target already owns. As with docmeta, name the columns explicitly if the user tables gained or lost columns between releases.
    • FoldersQFL_Folder, FolderFolders, FolderFiles, inserting only folder GUIDs that don't already exist on the target (the fresh instance ships with a root structure you don't want to duplicate).
    • Security/access log — clear the target's SctAccessLog and load the source's if you want access history to match.

    The pattern throughout: filter against what the fresh target already has, and name columns explicitly wherever the schema drifted.

    Step 5: repoint the filesystem — the step people forget

    Here's the layer that makes this a content clone and not just a database clone. The documents rows you copied point at files in the vault and weblayout directories. If those directories aren't present and the instance isn't told where they are, every content item resolves to nothing — the metadata is there, the file is a 404.

    Copy production's vault and weblayout trees to the clone host, then point each UCM server's config at them. In each intradoc.cfg (and per-server variants):

    VaultDir=/path/to/cloned/ucm/cs/vault/
    WeblayoutDir=/path/to/cloned/ucm/cs/weblayout/
    

    Now a metadata row and its actual file agree. This is the difference between a rehearsal you can click through and one that looks fine in a query and falls apart the moment a user opens a document.

    Step 6: reset the sequences — or the clone corrupts itself on first use

    This is the one that's invisible until it isn't. WCC uses database sequences to allocate the next ID for new content. You just bulk-loaded rows with IDs the sequence doesn't know about — so the sequence will happily hand out an ID that already exists, and the first check-in a user does collides.

    Find the current max on each key table and restart the sequence just past it:

    -- Revision ID
    select max(dID) from revisions;                 -- e.g. 1292127
    alter sequence IDCSEQREVID       restart start with 1292128;
    
    -- Revision-class ID
    select max(dRevClassID) from revisions;         -- e.g. 1067138
    alter sequence IDCSEQREVCLASSID  restart start with 1067139;
    
    -- Document ID
    select max(dDocID) from documents;              -- e.g. 2464060
    alter sequence IDCSEQDOCID       restart start with 2464061;
    
    -- Verify each
    select last_number from user_sequences where sequence_name = 'IDCSEQREVID';
    SELECT IdcSeqRevID.NEXTVAL from DUAL;
    

    Skip this and the clone looks perfect right up until someone adds content — then you're debugging a "duplicate ID" that has nothing to do with the upgrade you were trying to test. Do it, and the clone behaves like a live system.

    The max() values above are illustrative — the real ones are specific to your estate, and the sequence names themselves can vary by version and configuration. That's the point worth sitting with: this is not a fixed script you paste in. It's a pattern you apply against numbers only your data can give you, and the reset has to happen after the bulk load and before the first check-in — if the ordering slips, the collision is already baked in and no amount of re-running the ALTER afterward un-corrupts the rows that were handed a duplicate ID.

    Why this is the essential rehearsal step for 12c → 14c

    The platform upgrade guides tell you how to move the WebCenter Content runtime from one release to the next. What they can't tell you is how your content, your hundred custom metadata fields, your in-flight workflows, and your folder tree will behave when the upgrade runs — because that's specific to your estate. A faithful clone is how you find out on a system where the answer is free.

    And the clone pays for itself twice. The first time, it's your test-upgrade target: you run the 12c → 14c upgrade against it, watch what breaks, and fix your runbook before production is ever at risk. The second time, the schema-reconciliation work you did — the widened columns, the explicit column maps, the sequence resets — is the production runbook. You're not rehearsing a different task; you're doing the real one on a safe copy first.

    But here's the line the commands above can't cross for you: "it ran without error" is not "the clone is trustworthy." Every failure mode in this post — the wrong metadata written uniformly, the supporting table left behind, the sequence that hasn't collided yet — produces a clone that queries clean and looks live. Proving the clone actually mirrors production is a separate act of judgment: reconciling counts table by table, opening real documents and confirming the bytes and the metadata and the workflow state all agree, and knowing which of your custom components and integrations would expose a discrepancy this one didn't happen to touch. A clone you can't vouch for isn't a rehearsal — it's a second thing that might be wrong, and you'd be upgrading against a fiction while believing you were safe.

    That's the real question this work turns on, and it isn't a question a script answers: not "did the steps run?" but "can I stand behind this clone as a faithful copy of my estate — and if it breaks at 2am mid-cutover, do I know why?" With the December 2026 Premier Support date fixed, the shops that move calmly are the ones that can answer it. If your WebCenter Content instance is heavily customized, lightly documented, or the people who built it have moved on — reading the running system directly, deciding where the content-vs-machinery line falls, and being accountable for the result is exactly the kind of work this exists for. A scoping conversation is the right first step.


    This is a field runbook grounded in a real WebCenter Content clone-and-upgrade project, not a substitute for Oracle's WebCenter Content upgrade documentation for your specific source and target releases. Table names, column specifics, and sequence names vary by version and configuration — always validate against a non-production copy first.

    See it against your Oracle AP

    Book a 30-minute walkthrough — we'll run a real exception from supplier email to Oracle posting, on Fusion or EBS.