Skip to content

WW-5653 Upgrade Bootstrap to 5.3.x in sample apps#1793

Draft
lukaszlenart wants to merge 23 commits into
mainfrom
WW-5653-bootstrap5-sample-apps
Draft

WW-5653 Upgrade Bootstrap to 5.3.x in sample apps#1793
lukaszlenart wants to merge 23 commits into
mainfrom
WW-5653-bootstrap5-sample-apps

Conversation

@lukaszlenart

Copy link
Copy Markdown
Member

Fixes WW-5653

Migrates both sample apps — apps/showcase and apps/rest-showcase — off the vendored Bootstrap 3.3.4 assets onto Bootstrap 5.3.7, served via the framework's own <s:webjar> support. This is a minimal port: pages keep their structure and look; only what Bootstrap 5 breaks was changed. Zero vendored Bootstrap 3 assets and zero Bootstrap 3 markup remain.

Design + plan: docs/superpowers/specs/2026-07-17-WW-5653-bootstrap5-migration-design.md, docs/superpowers/plans/2026-07-17-WW-5653-bootstrap5-migration.md.

What changed

Asset delivery (WebJars)

  • Added org.webjars:bootstrap:5.3.7 and org.webjars.npm:bootstrap-icons:1.13.1 (managed in parent/pom.xml, version props in root pom.xml); both apps depend on them.
  • Deleted all vendored Bootstrap/jQuery static files; references now use <s:webjar> (bootstrap/css/bootstrap.min.css, bootstrap/js/bootstrap.bundle.min.js, bootstrap-icons/font/bootstrap-icons.min.css, jquery/jquery.min.js).
  • WebJar allowlist configured per app (struts.webjars.allowlist).

jQuery isolation (note for reviewers)

  • The showcase keeps jQuery (2 direct usages: prettyPrint + an AJAX demo), pinned to 3.7.1 via a dedicated webjars-jquery-showcase.version property. The shared webjars-jquery.version (now 4.0.0, core test scope) is intentionally not reused, so a future bump of the shared property won't drag the showcase to jQuery 4. Bootstrap 5 itself needs no jQuery.

Markup migration (BS3/BS2 → BS5)

  • Icons: glyphicon-* (and old BS2 icon-*) → Bootstrap Icons bi bi-*.
  • panel*card*, btn-defaultbtn-secondary, btn-largebtn-lg, wellbg-light border rounded p-3, pull-*float-*/ms-auto, table-condensedtable-sm, col-xs-*col-*, BS2 spanNcol-N, col-sm-offset-2offset-sm-2, data-*data-bs-*, page-header/hero-unit replaced, carets removed.
  • Navbar rewritten to BS5 (navbar-expand-lg, toggler + collapse, dropdown-toggle/dropdown-menu/dropdown-item).
  • rest-showcase horizontal forms → BS5 (row mb-3 + col-form-label); fixed a pre-existing malformed </apan> tag.

Runtime verification (manual, both apps under mvn jetty:run)

  • showcase: home + fileupload + wait + tag-demo pages return 200; all webjar assets serve 200 (Bootstrap CSS/JS bundle, Bootstrap Icons CSS, jQuery 3.7.1); remaining webapp assets (prettify.js, main.css) still serve.
  • rest-showcase: order pages render; Bootstrap + Bootstrap Icons CSS serve 200; bi icons render; no glyphicons in output.
  • Core webjar tests: 18/18 pass (jQuery 4.0.0 test-scope unaffected).

Dogfooding find (already fixed here)

Serving the showcase via <s:webjar> surfaced a real bug in the showcase's own config: struts.action.excludePattern still whitelisted the old vendored layout (.*/styles/.*\.css, .*/js/.*\.js). The .*/js/.*\.js entry matched the webjar JS path (/static/webjars/bootstrap/5.3.7/js/bootstrap.bundle.min.js), so StrutsExecuteFilter excluded it from the static handler and it fell through to the container and 404'd (silently — no Struts logs). The CSS worked only because its webjar path is under /css/, not /styles/. Fixed by dropping the obsolete /styles/ and /js/ exclude entries. No core/framework code was changed — this is showcase config only.

Draft — remaining follow-up nits (non-blocking)

  • Leftover harmless BS3 navbar-header wrapper div in decorators/main.jsp (no BS5 CSS behind it).
  • page-header replacement is border-bottom pb-2 mb-3 on most pages vs a bare <div> on a few — both valid, slightly inconsistent.
  • navbar-light is soft-deprecated in BS 5.3 (works fine in 5.3.7; data-bs-theme is the newer idiom).
  • Pre-existing orphan dropdown-submenu/unclosed <li> in the navbar Examples menu (not introduced here).

🤖 Generated with Claude Code

lukaszlenart and others added 23 commits July 17, 2026 20:56
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ap 5

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…vbar classes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…otstrap 5

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ootstrap 5

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…Home

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…otstrap 5

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…JS is served

The old struts.action.excludePattern whitelisted the vendored /styles/*.css
and /js/*.js layout for container serving. After moving Bootstrap/jQuery to
webjars under /static/webjars/**, the '.*/js/.*\.js' entry matched the webjar
JS path (e.g. bootstrap.bundle.min.js) and excluded it from Struts' static
handler, so it fell through to the container and 404'd. Remaining webapp assets
(prettify.js, main.css) are served via default-servlet fall-through.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ons, progress, forms, navbar)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lates

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…trap 5

HtmlUnit's JS engine cannot parse Bootstrap 5's ES6 (bootstrap.bundle.min.js
uses 'class'), and the decorator now serves it, so the default WebClient threw
on script error. The test only asserts server-rendered FreeMarker output, so
JavaScript is disabled (matching Html5TagExampleTest).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Migrate new-person.ftl form off BS2 control-group/controls/form-actions to
Bootstrap 5 (mb-3, form-label, form-control), and replace the dead alert-error
class with alert-danger across the showcase pages.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nder HtmlUnit

HtmlUnit 5.2.0 cannot parse Bootstrap 5's minified ES6 (bootstrap.bundle.min.js
uses 'class'), which broke the showcase HtmlUnit integration tests once the
decorator started serving the bundle.

- Add ParameterUtils.createWebClient() which disables throwExceptionOnScriptError,
  and route all integration tests through it (they assert server-rendered output,
  not Bootstrap's client-side behaviour).
- Load bootstrap.bundle.min.js with 'defer' so a page's own inline scripts (e.g.
  the async chat demo) still execute before HtmlUnit hits the bundle's parse
  error; defer is also the recommended real-browser loading strategy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.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.

1 participant