Skip to content

fix(push-publishing): prevent non-Host contentlets from being bundled as .host.xml - #36941

Open
gortiz-dotcms wants to merge 4 commits into
mainfrom
issue-34522-host-pp-non-host-xml
Open

fix(push-publishing): prevent non-Host contentlets from being bundled as .host.xml#36941
gortiz-dotcms wants to merge 4 commits into
mainfrom
issue-34522-host-pp-non-host-xml

Conversation

@gortiz-dotcms

Copy link
Copy Markdown
Member

Summary

  • HostBundler.writeFileToDisk() now skips any contentlet whose content type is not a Host (e.g. Widgets or regular content related to a Site via relationship field), preventing them from being incorrectly written with the .host.xml extension
  • ContentHandler adds a null-safety guard around hostAPI.find() as a secondary line of defense — logs a warning and skips host-only update steps instead of NPE-ing
  • Root cause: HostBundler.getRelatedFilesAndContent() calls findContentRelationships() and pulls ALL related contentlets unconditionally; those were then written as .host.xml files regardless of their actual content type, causing either a NotFoundInDbException (ContentType not on receiver) or NPE (host is null) when the receiver processed them

Test plan

  • Create a blank site and a Widget with a relationship field pointing to that site
  • Push publish the site using the "Only Selected Items" filter
  • Confirm push publish completes successfully with no NotFoundInDbException or NPE
  • Confirm the site arrives correctly on the receiver
  • Run integration test: ./mvnw verify -pl :dotcms-integration -Dcoreit.test.skip=false -Dit.test=ContentHandlerTest

Fixes #34522

🤖 Generated with Claude Code

… as .host.xml (#34522)

HostBundler.writeFileToDisk() now skips contentlets whose content type is
not Host (e.g. Widgets related via relationship field), preventing them
from being written with the .host.xml extension and causing a
NotFoundInDbException or NPE on the receiving server. ContentHandler adds
a null-safety guard as a secondary line of defense.

Refs: #34522

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@claude

claude Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Claude finished @gortiz-dotcms's task in 8m 2s —— View job


Code Review

I reviewed the diff against origin/main (the 4 PR commits on top of ca0a0d23). This is a focused, correct root-cause fix. Findings below.

New Issues

No blocking issues found.

Observations (non-blocking)

  • 🟡 Medium: HostBundler.java:119-122status.addCount() is incremented for contentlets the new guard skips (the loop always calls addCount() after writeFileToDisk, which now returns early for non-Host/non-FileAsset content). The bundler status count will overstate the number of files actually written. This mirrors the pre-existing SYSTEM_HOST early-return at line 318, so behavior is consistent — but if the count is used for reporting/verification it's slightly inaccurate. Minor; not blocking.

  • 🟡 Medium: ContentHandler.java:575-586 — the null guard is a sound secondary defense, but note that when host is genuinely expected on the receiver and find() returns null for a transient reason (not just the bundled-non-Host case), this now silently skips updateDefaultHost/updateCache with only a warn. Given the HostBundler fix prevents the actual bad input, this is acceptable defensive handling — just be aware the warning is the only signal if it ever fires for a real host.

Notes on correctness

  • HostBundler.java:321 — the guard !isHost() && !isFileAsset() correctly preserves FileAsset bundling (addressed by commit 5938f79a) while excluding Widgets/related content. isHost() (Contentlet.java:1467) resolves by content-type variable, which is the right check. ✅
  • The regression test at HostBundlerTest.java:126 is meaningful: without the guard, a related non-Host contentlet reaches writeFileToDisk, gets HOST_EXTENSION appended (line 391-401), and would be picked up by getFileFilter() (.host.xml). The path.contains(relatedContentId) assertion is valid since the identifier appears in the written URI. The test also asserts the Site itself is still bundled. ✅
  • The com.dotmarketing.util.FileUtilcom.liferay.util.FileUtil import swap and removal of the unused set static import are consistent with the fixups in 00153e16; no remaining references to the removed symbols. ✅
  • @BeforeClass prepare() plus the manual prepare() call inside the hosts() DataProvider is redundant but safe (IntegrationTestInitService.getInstance().init() is idempotent). ✅

Suggestions

  • Consider Logger.debug(this, () -> "...") (lambda form) at HostBundler.java:322 to avoid string concatenation when debug logging is disabled — matches the pattern already used elsewhere in the codebase (e.g. ContentHandler.java:563). Non-blocking.

Overall: clean, minimal, and addresses the root cause in the bundler with a reasonable defensive guard in the handler. Good test coverage for the regression.
• branch issue-34522-host-pp-non-host-xml

)

Narrow the !isHost() guard to also allow FileAsset contentlets through
writeFileToDisk(), since HostBundler deliberately collects and writes
file assets linked via FILE-type fields (line 396 uses isFileAsset to
produce an inode-based filename). The previous guard was too broad and
silently dropped those file assets. The ContentHandler null-safety check
added in the same PR handles the receiver side gracefully for both file
assets and non-Host types.

Refs: #34522

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gortiz-dotcms and others added 2 commits August 7, 2026 09:46
…undled as .host.xml (#34522)

Adds test_relatedNonHostContentlet_isNotBundledAsHostXml to verify that
a Widget related to a Site via a Relationship field is not written as a
.host.xml file when the Site is push-published with Only Selected Items.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use correct APILocator.getContentTypeAPI(User, boolean) signature,
switch FileUtil import to com.liferay.util.FileUtil for listFilesRecursively,
and use List<File> return type.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@claude

claude Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

dotCMS Backend Review: no issues found.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No Critical or High severity issues found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Safe To Rollback Area : Backend PR changes Java/Maven backend code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

[DEFECT] Host push publish issue using Only Selected Items, when host is attached to a contentlets relationship field.

1 participant