Changes since 25.2.1
New features
-
Reuse shared metadata cache when scanning (#24887) (CP: 25.2)
Commit · Pull request · IssueClass and annotation scanning at startup runs many passes (routes, error handlers, web components, lookup, ...), each building a new
ClassPathScanner. BecauseCustomResourceLoaderdoes not extendDefaultResourceLoader, Spring'sCachingMetadataReaderFactoryfalls back to a per-scan cache bounded to 256 entries instead of the application context's shared, unbounded resource cache. Parsed class metadata is therefore discarded and re-computed on every pass, slowing down startup on large classpaths. Keep the filteringCustomResourceLoaderas the scanner's pattern resolver so package and JAR filtering is preserved, and override the scanner'sMetadataReaderFactorywith a single sharedCachingMetadataReaderFactorybacked by the application context. As the context is aDefaultResourceLoader, the factory now stores metadata in the context's shared cache and reuses it across all scan passes. -
Add configurable max request body size (#24866) (CP: 25.2)
Commit · Pull requestAdd maxRequestBodySize property to limit UIDL/RPC and push request body size (-1 disables); the default is 10 MB; does not affect uploads.
Fixes
-
Support gradle 9 in plugin (#24891) (CP: 25.2)
Commit · Pull request · IssueBump kotlin and dokka versions. Add tests for 9.0.0 and 9.5.0
-
Clean up countInstances (#24890) (CP: 25.2)
Commit · Pull request · IssueMake count instances more effective by not using split that compiles a pattern and generates an array for each invocation.
-
Allow embedded web components to connect behind a modal (#24857) (CP: 25.2)
Commit · Pull requestEmbedded web components share a single WebComponentUI and are attached as children of its element. When one of them opens a modal component, the WebComponentUI element becomes inert, which dropped the connect-web-component RPC for any other embedded web component connecting or reconnecting while the modal is open. Mark the connect event with allowInert so the connect handshake bypasses the server-side modality filter, matching how polling and navigation are handled.
-
Keep dev mode running when a pre-trial is expired
Commit · Pull requestIn dev mode with dev tools enabled, an expired pre-trial threw PreTrialLicenseValidationException, which aborted server startup so the splash screen was no longer shown. Catch it for the expired state and delegate to dev tools like a missing key; other states are rethrown.
-
Keep component-fullscreen working when target is the view root (#24785) (CP: 25.2)
Commit · Pull requestrequestComponentFullscreen captured the view root to hide via wrapper.firstChild after inserting the placeholder comment and moving the element into the wrapper. When the fullscreened component is the wrapper's direct child (the route view root), the placeholder becomes the wrapper's first node, so firstChild returned the comment and reading .style.display on it threw "Cannot read properties of undefined". Capture the view root via firstElementChild before mutating the DOM so comment/text nodes are skipped, and skip hiding when the fullscreened component is itself the view root (hiding it would blank the screen).
-
Move internal frontend sources out of deprecated location (#24851) (CP: 25.2)
Commit · Pull request · Issueflow-reactandflow-dndshipped their@JsModulebundle sources (ReactRouterOutletElement.tsxanddndConnector.js) under the deprecatedMETA-INF/resources/frontend/location. With recent builds this triggers a per-jar deprecation warning. - MovedReactRouterOutletElement.tsxanddndConnector.jstoMETA-INF/frontend/, the current location for@JsModule/@CssImportbundle sources. - Updated theReactRouterOutletentry-point detection inFrontendDependenciesto resolve the resource from the new location, falling back to the legacyMETA-INF/resources/frontend/location for backwards compatibility with older add-on jars. Eliminates the per-jar deprecation warning emitted during the build while keeping older add-on jars (which still ship sources in the legacy location) working. -
Keep project version data in telemetry after a clear (#24827) (CP: 25.2)
Commit · Pull requestThe dev-mode usage statistics file is shared by all dev servers running on a machine. After a successful upload StatisticsSender clears the whole projects array, which also wipes the data of other still-running dev servers that did not trigger the upload. Until now the version and source identity (flowVersion, vaadinVersion, hillaVersion, sourceId) was only written by trackGlobalData() at dev-mode startup, so any event from a continued session (live reload, browser data, ...) recreated the project entry with just that event's field and no versions. The next report then contained rows with an empty flowVersion and devModeStarts == 0. Re-assert the project identity data whenever the running session writes project data and the entry is missing it, so a continued session repairs its own entry before the next report is sent. devModeStarts stays a true per-interval counter (0 for a continued session) but now always comes with complete version information.
-
Preserve dev-server generated frontend files during prepare-frontend (#24679) (CP: 25.2)
Commit · Pull requestA standalone prepare-frontend run cleans the frontend generated folder by deleting any file the run did not itself produce. Files generated only by a full generation run (dev server hot deploy, bundle or production build) - index.tsx, vaadin-react.tsx, layouts.json, flow/ReactAdapter.tsx, vite-devmode.ts - are not regenerated by prepare-frontend, so the cleanup removed them out from under the running app: a missing vite-devmode.ts triggers an infinite reload loop and a missing index.tsx/vaadin-react.tsx breaks the vaadin.ts import graph and shows a Vite error. Record the files produced by a generation run in a manifest, and have the cleanup read it the same way it already reads Hilla's generated-file-list. prepare-frontend does not perform a full generation, so it reads the manifest but never overwrites it, and therefore preserves these files instead of deleting them. Because every generation run rewrites the manifest in full, a file that is no longer generated (e.g. after disabling React) is dropped and cleaned up on the next run - something a hardcoded allow-list could not do. Related to #24108
-
Allow UI polling while a modal component is open (#24834) (CP: 25.2)
Commit · Pull request · IssuePoll listeners registered through
PollNotifier.addPollListenerare now registered withDomListenerRegistration::allowInert, so they continue to fire even when a modal component makes the UI inert. UI polling is a global, UI-level feature. It is not tied to any specific component and does not send user-controlled data to the server, so it should not be blocked by a modality curtain. Previously, opening a modal dialog caused poll events to be dropped with an"Ignored listener invocation for ui-poll event ... inert"message, effectively stopping polling for the duration the modal was open. -
Ignore empty entries when parsing postinstall package lists (#24831) (CP: 25.2)
Commit · Pull request · IssueSplitting an empty configuration value on "," yields an array with a single empty string instead of an empty array. That empty entry was passed on to TaskRunNpmInstall, which then attempted to run a postinstall for a package with an empty name. Parse the additional and exclude postinstall package properties through a shared helper that trims entries and drops blank ones, so an unset property results in an empty list.