feat: auto-convert fragments referenced by a form during job execution - #240
feat: auto-convert fragments referenced by a form during job execution#240im-shiv wants to merge 1 commit into
Conversation
After converting a form, scan its JCR tree for fragRef/fragmentPath references. For each found fragment: copy to <targetRoot>/fragments/, convert in place using the same rule pipeline, then update all path references in the converted form. A convertedFragments set skips duplicates within the same bucket. Warnings (path||message) are stored in the bucket resource for any node that still carries an AF1 sling:resourceType after conversion.
|
@im-shiv Could you share a summary of the issue and approach. Does it cover below scenarios:
|
In-place migration Out-of-place migration
Leveraging already-migrated fragments (out-of-place) |
This needs to be resolved - since someone may update the fragment after first creation - which would result in effort loss. There should be an option to leverage already existing fragments. |
Review comments from claude:PR #240 — Code Review feat: auto-convert fragments referenced by a form during job execution Overview The PR extends FormConversionJobExecutor.doProcess to automatically detect, copy, and convert AF1 form fragments that are referenced by a form. Fragments are collected by scanning the JCR tree for fragRef properties, copied into a fragments/ Critical Bugs 1. fragRef is scanned but only fragmentPath is updated — likely a path-update miss collectFragmentRefs finds nodes with fragRef: 2. Potential NullPointerException on adaptTo(Node.class) Both call sites chain directly off the result without null checks: // doProcess: 3. Session never saved after normalizeTargetRoot and ensureFolderExists Both helpers call JcrUtil.createPath(..., false) — the final false disables auto-save. Folder creation is queued in the pending session but never explicitly flushed. The first subsequent JCR read can see it within the same session, but if the 4. getProperty(…).getString() on potentially multi-valued properties In collectFragmentRefs and updateFragmentPaths: 5. Flat name extraction in updateFragmentPaths causes collisions String fragName = oldPath.substring(oldPath.lastIndexOf('/') + 1); Design Issues 6. No version created for fragment pages before in-place conversion For COPY mode, fragments are copied then converted — the source is untouched. But for non-COPY modes (convertFragmentInPlace), RewriteUtils.createVersion is never called on the fragment page. A failed fragment conversion leaves the fragment 7. Fragment conversion happens before form's own component-rule pass convertReferencedFragments(...); // ← fragments converted first 8. rr.adaptTo(Session.class).save() saves ALL pending changes globally The single .save() at the end of the COPY+fragment block commits everything pending in the session — including partial changes from earlier failed iterations within the same bucket. This is consistent with how JCR sessions work, but it's 9. convertedFragments deduplication key is the raw fragRef value If one form uses a DAM path (/content/dam/formsanddocuments/…) and another uses the AF path (/content/forms/af/…) to reference the same fragment, the same fragment is converted twice and copied to the same destination — the second copy will Missing Test Coverage The PR adds 182 lines of new logic but no new tests. The existing tests (doProcessNoReprocess, doProcessReprocess) have no fixture data with fragRef/fragmentPath properties, so the new paths are entirely untested. At minimum, tests are needed
Minor / Style
|
bstopp
left a comment
There was a problem hiding this comment.
See PR review from Claude provided by @iamsudhanshu
After converting a form, scan its JCR tree for fragRef/fragmentPath references. For each found fragment: copy to /fragments/, convert in place using the same rule pipeline, then update all path references in the converted form. A convertedFragments set skips duplicates within the same bucket. Warnings (path||message) are stored in the bucket resource for any node that still carries an AF1 sling:resourceType after conversion.