Skip to content

fix(checkbox): guard against null uncheckedValue when JCR property is absent#1892

Merged
rismehta merged 1 commit into
devfrom
fix/checkbox-null-unchecked-value
May 29, 2026
Merged

fix(checkbox): guard against null uncheckedValue when JCR property is absent#1892
rismehta merged 1 commit into
devfrom
fix/checkbox-null-unchecked-value

Conversation

@rismehta
Copy link
Copy Markdown
Collaborator

Summary

  • Root cause: When enableUncheckedValue=true and uncheckedValue is empty string, content push mechanisms omit empty-string properties when writing to JCR. The property is absent, so @ValueMapValue(OPTIONAL) injects null. AbstractCheckboxImpl.initBaseCheckboxModel() builds enum: [".", null].
  • Crash: AFB runtime calls .toString() on every enum value at init — null.toString() throws TypeError in createFormInstance / RuleEngineWorker, crashing the form before any screen renders.
  • Fix: Default uncheckedValue to "" when the JCR property is absent.
  • Test: Fixture checkbox-enableUncheckedValueMissingFromJcr omits uncheckedValue from JCR; asserts getEnums() returns [".", ""] not [".", null].

Why af-form-json-converter did not catch this

The converter loads form JSON via context.load().json() into a mock JCR (HashMap-backed). The mock stores the literal empty string and returns it to the Sling model. Real AEM never receives that empty string because the push pipeline drops empty-string properties — so the property is absent and uncheckedValue is injected as null.

Test plan

  • CheckBoxImplTest#shouldUseEmptyStringWhenUncheckedValueMissingFromJcr passes
  • All 35 existing CheckBoxImplTest tests still pass
  • Verify on HDFC env after bumping core components version

Generated with Claude Code

… absent

When enableUncheckedValue=true but uncheckedValue is not stored in JCR
(e.g. because the content push mechanism skipped an empty-string value),
AbstractCheckboxImpl built an enum array with null as the second element.
The AFB runtime calls .toString() on every enum value at init time, so
enum: [".", null] caused TypeError: Cannot read properties of null
(reading 'toString') in createFormInstance / RuleEngineWorker, crashing
the form before any screen rendered.

Fix: default safeUncheckedValue to "" when the JCR property is absent.
Add a regression test with a fixture that omits uncheckedValue from JCR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot force-pushed the fix/checkbox-null-unchecked-value branch from c9d16e1 to 5e8262f Compare May 28, 2026 06:55
@adobe-bot
Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

@adobe-bot
Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
page-has-heading-one moderate
target-size serious

@adobe-bot
Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
target-size serious

@adobe-bot
Copy link
Copy Markdown

Accessibility Violations Found

Id Impact
aria-required-attr critical
empty-heading minor
label-title-only serious
page-has-heading-one moderate
target-size serious

@codecov
Copy link
Copy Markdown

codecov Bot commented May 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@rismehta rismehta merged commit 672b1a4 into dev May 29, 2026
8 checks passed
@rismehta rismehta deleted the fix/checkbox-null-unchecked-value branch May 29, 2026 04:36
prateek1497 added a commit that referenced this pull request May 29, 2026
* Updating style selectors for theme editor

* Updating style selectors further

* Merge pull request #1872 from adobe/fix/FORMS-25246-fieldtype-containers

feat(dialog): add fieldType hidden field to container component dialogs

* fix(checkbox): guard against null uncheckedValue when JCR property is absent (#1892)

When enableUncheckedValue=true but uncheckedValue is not stored in JCR
(e.g. because the content push mechanism skipped an empty-string value),
AbstractCheckboxImpl built an enum array with null as the second element.
The AFB runtime calls .toString() on every enum value at init time, so
enum: [".", null] caused TypeError: Cannot read properties of null
(reading 'toString') in createFormInstance / RuleEngineWorker, crashing
the form before any screen rendered.

Fix: default safeUncheckedValue to "" when the JCR property is absent.
Add a regression test with a fixture that omits uncheckedValue from JCR.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(af-core): FORMS-25463 expose cq:annotations parallel to fd:dor (#1883)

* feat(af-core): FORMS-25463 expose cq:annotations parallel to fd:dor

Add getCqAnnotations() on AbstractFormComponentImpl that reads the
cq:annotations child resource (a sibling of fd:dorContainer on the
component node) and exposes its child annotations as a per-annotation
map keyed by node name. Each entry carries color, text, x, y, optional
state/resolvedBy/resolvedAt and the JCR audit fields. Null fields are
stripped so the serialised shape matches the JCR content exactly.

Wire the call into getProperties() so the resulting map is placed
under properties.cq:annotations -- parallel to fd:dor / fd:path /
fd:associate -- not nested inside dorContainer. Returns null when no
cq:annotations child exists; Jackson then omits the key, keeping the
output non-breaking for forms without annotations.

* fix(af-core): FORMS-25463 exclude cq:annotations from getCustomProperties

getCustomProperties() reads all non-reserved JCR properties from the
resource ValueMap and includes them as raw Strings. cq:annotations is
not in the excluded-prefix list ("fd:", "jcr:", "sling:"), so a stale
String-typed cq:annotations property on the node was leaking through and
appearing as a double-serialised JSON string in the GET IC response.

Adding an explicit key exclusion for CUSTOM_ANNOTATIONS_PROPERTY_WRAPPER
ensures the property is handled exclusively by getCqAnnotations(), which
returns it as Map<String,Object> and produces proper nested JSON.

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

* feat(af-core): FORMS-25463 ic annotations in authoring crispr only

* style(af-core): FORMS-25463 apply formatter to AbstractFormComponentImpl

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

* feat(af-core): FORMS-25463 ic annotations in authoring crispr only

* fix(af-core): FORMS-25463 remove formatting changes, keep only cq:annotations feature

* FORMS-25463: blocking publish of cq:annotations

* FORMS-25463: adding tests

* FORMS-25463: adding more tests for codecov

* FORMS-25463: formatting fix

* FORMS-25463: PR comments incorporate plus tests

---------

Co-authored-by: Prateek Awasthi <prateekawast@adobe.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Muskan Gupta <muskgupta@Muskans-MacBook-Pro.local>
Co-authored-by: Varun Dua <vdua@adobe.com>
Co-authored-by: muskgupta <muskgupta@adobe.com>
Co-authored-by: Rishi Mehta <69448117+rismehta@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Prateek Awasthi <prateekawast@adobe.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants