Releases: vaadin/flow
Vaadin Flow 25.1.0-beta3
Changes since 25.1.0-beta2
Breaking changes
-
Make localeSignal() read-only on VaadinSession and UI (#23828)
Commit · Pull requestReturn Signal instead of SharedValueSignal/ValueSignal from localeSignal() so that all locale changes go through setLocale(), which handles UI propagation and LocaleChangeObserver notification. Add javadoc showing two-way binding pattern with bindValue and setLocale. Add tests for bindValue-based locale switching, UI locale independence from session, and session setLocale with per-UI override.
-
Split computed into separate cached and direct versions (#23822)
Commit · Pull requestPreviously, the
computedmethod was just one out of many ways of creating a computed signal with the distinction that this computed signal was also caching. This made it difficult to understand when to use the method. computed signal and introducing a separatecachedmethod that creates a cached signal out of any other signal. signals
New features
-
Apply ElementEffect once when created (#23824)
Commit · Pull request · IssueElementEffect is executed immediately once when created. This affects all Signal.effect calls with an owner component. Immediate execution ensures that exceptions can be thrown eagerly when e.g. bindText(signal) is called, not later when component is attached.
-
Throw binding exception if setItems is called while an active signal binding (#23807)
Commit · Pull request · Issue -
Add bindItems to HasDataProvider components (#23761)
Commit · Pull request
Fixes
-
Skip ElementEffect callback on reattach when no signals changed (#23771)
Commit · Pull request · IssueAdd passivate/activate lifecycle to Effect so that ElementEffect can preserve tracked Usage instances across detach/attach cycles. On reattach, activate checks whether any dependency has changed since passivation: if so, the callback re-runs with isInitialRun=true; if not, only the dependency listeners are re-registered without invoking the callback, avoiding redundant work and confusing double invocations.
-
Allow local signal reads in computed callbacks triggered from transaction commit (#23791)
Commit · Pull request · IssueDuring the StagedTransaction commit phase, listener callbacks that re-evaluate computed signals could not read local signals because inExplicitTransaction() still returned true. The transaction is no longer staging commands at that point, so local signal access is safe.
-
Move import statements to top in generated web component imports file (#23817)
Commit · Pull requestAbstractUpdateImports.process()already reordersimportlines to the top forgeneratedFlowImports, but the same sorting was not applied togeneratedFlowWebComponentImports. This caused interleavedimportand non-import lines (e.g.injectGlobalWebcomponentCss()calls mixed withimportstatements) in the web component output. Extract a reusablemoveImportsToTop()method and apply it both inprocess()for main imports and inmergeWebComponentOutputLines()after merging and deduplicating the web component sources. Related to #23689 (comment) -
Improve npm resolution for non-windows (#23810)
Commit · Pull requestAdds another potential path to the npm resolver algorithm to make it compatible with node installation performed by frontend-maven-plugin
-
Detect router-link attribute in ancestor elements during click navigation (#23786)
Commit · Pull requestWhen a nested element (e.g., Button) inside a RouterLink is clicked, the navigation trigger was incorrectly reported as CLIENT_SIDE because only the direct click target was checked for the router-link attribute. Traverse the composed path instead so any ancestor with router-link is correctly identified as a ROUTER_LINK trigger.
Tests
-
Migrate flow-polymer-template tests to JUnit 6 (#23625)
Commit · Pull request -
Migrate flow-build-tools tests to JUnit 5 (#23623)
Commit · Pull request -
Migrate flow-data tests to JUnit 5 (#23599)
Commit · Pull requestConvert 71 test files from JUnit 4 to JUnit 5: - Replace JUnit 4 imports with JUnit 5 equivalents - Before/After -> BeforeEach/AfterEach - Test(expected=X.class) -> assertThrows(X.class, ...) - ExpectedException Rule -> assertThrows + message assertions - Assert.xxx() -> static imports from Assertions - Message-first assertions reordered to message-last - RunWith(Parameterized.class) -> ParameterizedTest + ValueSource for DataCommunicatorTest and DataCommunicatorAsyncTest - Visibility adjustments for cross-package inheritance
-
Migrate vaadin-dev-server tests to JUnit 6 (#23622)
Commit · Pull request
Vaadin Flow 24.10.0-beta1
Changes since 24.10.0-alpha2
Fixes
-
Detect router-link attribute in ancestor elements during click navigation (#23786)
Commit · Pull requestWhen a nested element (e.g., Button) inside a RouterLink is clicked, the navigation trigger was incorrectly reported as CLIENT_SIDE because only the direct click target was checked for the router-link attribute. Traverse the composed path instead so any ancestor with router-link is correctly identified as a ROUTER_LINK trigger.
-
Log instead of throwing (#23692)
Commit · Pull request · IssueLog instead of throwing when node_modules removal fails in cleanUp.
-
Clamp effectiveRequested range in DataCommunicator to prevent IndexOutOfBoundsException (#23672)
Commit · Pull request · IssueWhen a data provider returns fewer items than its size() reports (e.g. items deleted between the count and fetch queries), getJsonItems() would crash with an IndexOutOfBoundsException. Clamp effectiveRequested to match the actual number of fetched items before processing changes.
-
Use raw request URI for baseHref calculation to support encoded slashes (#23569)
Commit · Pull request · IssueThe previous fix for encoded slashes (%2F) in wildcard route parameters (commit b0c121b) set urlPathHelper.setUrlDecode(false) in ForwardingRequestWrapper, which made getPathInfo() return percent-encoded paths for all requests. This broke static resource serving for files with spaces in their names and potentially affected other getPathInfo() consumers like DAUUtils. Instead of disabling URL decoding globally, fix the actual site where the raw path matters: BootstrapHandlerHelper.getServiceUrl(). This method uses getCancelingRelativePath() to count path segments for the baseHref, which must use the raw URI so that %2F is not mistaken for a real path separator. The fix computes the raw path info by stripping the context path and servlet path from the request URI, preserving the original encoding. This allows reverting setUrlDecode(false) so that getPathInfo() returns properly decoded paths for all consumers.
Vaadin Flow 25.0.8
Changes since 25.0.7
Fixes
-
Detect router-link attribute in ancestor elements during click navigation (#23786)
Commit · Pull requestWhen a nested element (e.g., Button) inside a RouterLink is clicked, the navigation trigger was incorrectly reported as CLIENT_SIDE because only the direct click target was checked for the router-link attribute. Traverse the composed path instead so any ancestor with router-link is correctly identified as a ROUTER_LINK trigger.
-
Make flattened TreeDataProvider consider entire hierarchy when filtering (#23691)
Commit · Pull requestWhen filtering in FLATTENED hierarchy format, ancestors were not shown if a filter matched a descendant that was not expanded. Now the provider recurses into collapsed subtrees to check for matching descendants, ensuring ancestors are included in the result even when the matching descendant is not expanded.
-
Log instead of throwing (#23692)
Commit · Pull request · IssueLog instead of throwing when node_modules removal fails in cleanUp.
-
Clamp effectiveRequested range in DataCommunicator to prevent IndexOutOfBoundsException (#23672)
Commit · Pull request · IssueWhen a data provider returns fewer items than its size() reports (e.g. items deleted between the count and fetch queries), getJsonItems() would crash with an IndexOutOfBoundsException. Clamp effectiveRequested to match the actual number of fetched items before processing changes.
Tests
- Suppress duplicate WEB-INF/lib JAR scan warnings in Jetty (#23740) (CP: 25.1) (#23756)
Commit · Pull request
Vaadin Flow 24.9.14
Changes since 24.9.13
Fixes
-
Detect router-link attribute in ancestor elements during click navigation (#23786) (#23800)
Commit · Pull requestWhen a nested element (e.g., Button) inside a RouterLink is clicked, the navigation trigger was incorrectly reported as CLIENT_SIDE because only the direct click target was checked for the router-link attribute. Traverse the composed path instead so any ancestor with router-link is correctly identified as a ROUTER_LINK trigger.
-
Log instead of throwing (#23692)
Commit · Pull request · IssueLog instead of throwing when node_modules removal fails in cleanUp.
-
Clamp effectiveRequested range in DataCommunicator to prevent IndexOutOfBoundsException (#23672)
Commit · Pull request · IssueWhen a data provider returns fewer items than its size() reports (e.g. items deleted between the count and fetch queries), getJsonItems() would crash with an IndexOutOfBoundsException. Clamp effectiveRequested to match the actual number of fetched items before processing changes.
Vaadin Flow 25.1.0-beta2
Changes since 25.1.0-beta1
New features
-
Add setTestId/getTestId convenience methods to Component (#23775)
Commit · Pull request · Issue -
Add SignalBinding with rich BindingContext for bind methods (#23670)
Commit · Pull requestAll Element bind methods (bindText, bindEnabled, bindVisible, bindProperty, bindAttribute, etc.), and Style.bind(), bindWidth(), bindHeight(), ThemeList.bind(), HasStyle.bindClassNames(), and HasTheme.bindThemeNames() now return SignalBinding object instead of void. SignalBinding exposes an onChange callback that receives a BindingContext with the old value, new value, whether it's the initial run, and the bound element/component. ElementEffect.bind() creates the SignalBinding internally and wires the effect registration into it so callers can control the effect lifecycle.
-
Allow setProperty if signal write callback is present (#23732)
Commit · Pull request · IssueThis change allows setting element property value if signal binding's write callback is present (not null). Each Element setProperty method is updated to change the signal value with the same logic as with a property value change from the client did before (and same logic as in HasValue#bindValue two-way binding). One-way binding, with null write callback, works same as before and throws BindingActiveException.
-
Add content-hash cache busting for Stylesheet URLs (#23544)
Commit · Pull request- In production mode, append a
?v-c=<8-char-sha256>query parameter toStyleSheetURLs so browsers reload only when file content changes, enabling aggressive caching withCache-Control: max-age=31536000, immutablefor versioned requests. - Content hashing is applied in both the AppShell path (AppShellRegistry.addStyleSheets) and the component dependency path (UidlWriter.dependencyToJson), covering allStyleSheetusage. -StaticFileServernow returns a 1-year immutable cache header when thev-cquery parameter is present in production mode, instead of the default short-lived cache.
- In production mode, append a
Fixes
-
Shared Signal.get() should throw outside reactive context with fallback transaction (#23760)
Commit · Pull request · IssueThe reactive context check in AbstractSharedSignal.get() used Transaction.inTransaction() which returns true when a session-scoped fallback transaction is active. This caused shared signals to silently allow get() calls outside reactive contexts when the session lock was held (e.g. in onAttach), unlike local signals which correctly threw. Changed the check to use Transaction.inExplicitTransaction() so that only explicitly started transactions (via runInTransaction) count as a valid reactive context, matching the behavior of local signals.
-
Skip validation on signal effect initial run in Binder (#23749)
Commit · Pull request · IssueThe reactive signal effect created by initInternalSignalEffectForValidators() was firing validation on its initial run when deferred to component attach, causing required fields to be marked invalid immediately on navigation. Use the context-aware Signal.effect() variant and skip fireValidationEvents on the initial run, so validation only triggers on actual value changes.
-
Preserve scroll position of all scrollable elements after hot-swap (#23722)
Commit · Pull request · IssueCapture and restore scroll positions of all scrollable elements during hot-swap UI refresh and full page reload. Elements are identified by CSS selector paths built from nth-of-type selectors anchored to the nearest ancestor with an ID, so elements without explicit IDs are also supported. The window scroll position uses a special window key. Only elements with non-zero scroll are captured, keeping the snapshot small. Both code paths are updated: the vaadin-dev-tools TypeScript (used for dev server WebSocket-triggered refreshes and full reloads via sessionStorage) and the Hotswapper Java inline JS (used for the vaadin-refresh-ui custom event).
-
Add SignalBindingFeature by default for text state node
Commit · Pull requestSupporting SignalBindingFeature by default removes danger to get IllegalStateException when using StateNode#getFeatureIfInitialized(Class) to get SignalBindingFeature.
-
Use absolute path for Aura CSS resource availability check
Commit · Pull requestThe isResourceAvailable call used the relative path "aura/aura.css" which, after URI resolution, was passed unchanged to ServletContext.getResource(). The Servlet specification requires paths to start with "/" and the missing leading slash caused a MalformedURLException, making the check always fail and flooding logs with warnings on every page load.
-
Exclude duplicate flow-build-tools JAR from WAR packaging
Commit · Pull requestThe maven-shade-plugin replaces the main artifact's file reference with shaded content during reactor builds, causing both flow-build-tools.jar and flow-build-tools-shaded.jar (byte-identical) to end up in test WAR WEB-INF/lib directories. This produces hundreds of duplicate-class warnings from Jetty's AnnotationParser. Add a packagingExcludes regex to the maven-war-plugin configuration in the root POM's pluginManagement to exclude the non-shaded JAR while keeping the shaded one.
Tests
- Suppress duplicate WEB-INF/lib JAR scan warnings in Jetty (#23740) (CP: 25.1)
Commit · Pull request
Vaadin Flow 25.1.0-beta1
Vaadin Flow 25.1 introduces production-ready reactive UI state management aka Signals API, along with the free browser-less testing framework (aka old commercial UI unit testing) and various other enhancements and bug-fixes.
Breaking Changes
Signal API Changes
-
Enforce signal reads in computed signals and effects
Commit · Pull requestSignals now enforce reactive context requirements when reading values in computed signals and effects.
-
Standardize signal callback interfaces
Commit · Pull request -
Move component-bound effect to Signal public API
Commit · Pull request -
Remove WritableSignal interface and simplify signal API
Commit · Pull requestSimplified the signal API by removing the WritableSignal interface and consolidating functionality.
-
Rename Signal value()/value(T) to get()/set(T)
Commit · Pull requestRenamed signal methods for clarity and consistency with Java conventions.
-
Restructure signals package for clarity between shared and local signals
Commit · Pull request -
Merge signals module into flow-server
Commit · Pull requestThe separate signals module has been merged into flow-server for better integration.
-
Rename Binder.Binding.value() to valueSignal() and return signal
Commit · Pull requestReworks Binding.value() to return a ValueSignal instead of the raw value.
-
Rename getValidationStatus() to validationStatusSignal()
Commit · Pull requestRenames the Binder method to better reflect that it returns a Signal.
Component and API Changes
-
Make wrapperElement field private
Commit · Pull requestThe wrapperElement field is now private and moved to UIInternals.
-
Prevent lumo utility classes from being imported automatically
Commit · Pull request · Issue -
Set proper value of isFromClient when using Focusable focus() and blur()
Commit · Pull requestThe isFromClient flag now properly reflects the origin of focus/blur events.
-
BeforeEvent target as extends Component
Commit · Pull request
Browser Compatibility
-
Update old browser check to verify compatibility with Vaadin 25+
Commit · Pull request · IssueUpdated browser compatibility check to ensure Popover API availability, required for Vaadin 25 web components.
New Features
Signal-Based Reactive Programming
-
Use type-parameter-level nullability for Signal APIs
Commit · Pull request -
Add custom equality checker support to ValueSignal
Commit · Pull request -
Throw IllegalStateException when Signal.get() is called outside a reactive context
Commit · Pull request -
Make shared signals use asynchronous signal trees
Commit · Pull request -
Detect accidental sharing of ValueSignal with background threads
Commit · Pull request -
Detect accidental sharing of local signals between sessions
Commit · Pull request -
Automatic repeatable reads for shared signals while session is locked
Commit · Pull request -
Make shared signals Serializable
Commit · Pull request -
Add local ListSignal for per-entry reactive lists
Commit · Pull request -
Add two-way computed signals via WritableSignal.map
Commit · Pull request -
Remove FLOW_FULLSTACK_SIGNALS feature flag and enable signals by default
Commit · Pull request -
Prevent serialization of shared signals
Commit · Pull request -
Add equality checker to ListSignal
Commit · Pull request -
Add moveTo method to ListSignal
Commit · Pull request
Component Signal Bindings
-
Add signal bind methods for NativeDetails, HtmlObject, and HasStyle
Commit · Pull request -
Add bindRequiredIndicatorVisible to HasValue / HasValueAndElement
Commit · Pull request -
Add windowSizeSignal() to Page for reactive window size tracking
Commit · Pull request -
Add localeSignal() to UI and VaadinSession
Commit -
Add signal binding constructors and methods for HTML components
Commit · Pull request -
Add bindChildren method to HasComponents mix-in
Commit · Pull request -
Add Anchor signal-based constructors
Commit · Pull request -
Add FieldSet::bindLegendText
Commit · Pull request -
Add Html(signal) and bindHtmlContent(signal)
Commit · Pull request -
Add bindWidth(Signal) and bindHeight(Signal)
Commit · Pull request -
Add bindReadOnly(Signal)
Commit · Pull request -
Add HasValidation::bindErrorMessage and bindInvalid
Commit · Pull request -
Add HasPlaceholder::bindPlaceholder(Signal)
Commit · Pull request -
Add HasHelper::bindHelperText
Commit · Pull request -
Add HasTheme::bindThemeName(String, Signal)
Commit · Pull request -
Add signal constructor to HTML components
Commit · Pull request · Issue -
Add HasValue::bindValue(WritableSignal)
Commit · Pull request · Issue -
Add HasText::bindText
Commit · Pull request · Issue -
Add Component::bindVisible
Commit · [Pull...
Vaadin Flow 25.1.0-alpha14
Changes since 25.1.0-alpha13
New features
-
Use type-parameter-level nullability for Signal APIs
Commit · Pull requestFollow Java's List pattern where nullability flows from the type argument rather than being hardcoded on method signatures. This makes Signal.get() return non-null String while Signal.get() returns AtNullable String. Key changes: - All signal type parameters use bound - Remove explicit AtNullable from public method signatures (get, peek, set, replace, map, computed, etc.)
Vaadin Flow 25.1.0-alpha13
Changes since 25.1.0-alpha12
Breaking changes
-
Enforce signal reads in computed signals and effects
Commit · Pull requestHelp detect cases where a value is assumed to update reactively even though it isn't by throwing an exception whenever an effect or computed signal doesn't depend on any signal value.
New features
-
Add signal bind methods for NativeDetails, HtmlObject, and HasStyle
Commit · Pull request -
Add custom equality checker support to ValueSignal
Commit · Pull request · IssueOptimize ValueSignal to skip updates when the new value equals the current value, and allow customization of equality logic. Changes: - Add SerializableBiPredicate<T, T> field for custom equality checking - Add constructor accepting custom equality checker (defaults to Objects::equals) - Update set() to skip updates when values are equal per equality checker - Update update() to use equality checker instead of reference equality - Add comprehensive tests for default and custom equality checkers.
-
Throw IllegalStateException when Signal.get() is called outside a reactive context
Commit · Pull request · IssueSignal.get() now throws when called outside a reactive context (effect, computed signal, untracked block, or transaction) to prevent accidental non-reactive reads like
new Span("Name: " + nameSignal.get())that silently return the value but never update. Users should use peek() for one-time reads. Key changes: - UsageTracker: add DELIBERATELY_UNTRACKED sentinel so untracked() sets a sentinel instead of removing the tracker, distinguishing "deliberately untracked" from "no tracking context" - AbstractLocalSignal/AbstractSignal: guard get() with isGetAllowed() check (shared signals also allow get() inside transactions) - ComputedSignal: remove peek() override so computed signals can be read outside reactive contexts via inherited AbstractSignal.peek() - Production code: use peek() where get() was called outside reactive contexts (Html, VaadinSession, SharedMapSignal.toString, Binder) -
Make shared signals use asynchronous signal trees
Commit · Pull request · IssueShared signals (SharedValueSignal, SharedListSignal, SharedMapSignal, SharedNodeSignal) now use LocalAsynchronousSignalTree instead of SynchronousSignalTree. This aligns with future clustered implementations where confirmation happens asynchronously via an event log. Key changes: - Add LocalAsynchronousSignalTree that dispatches confirm() on Vaadin's service executor - Adjust confirm() to skip observer notification when confirmed commands were at the head of the unconfirmed queue (no state change) As a side effect, all signals in a transaction must be from the same tree.
-
Add bindRequiredIndicatorVisible to HasValue / HasValueAndElement
Commit · Pull requestAllow all HasValueAndElement components to bind the required indicator visible state to a Signal, following the same pattern as bindReadOnly.
-
Add windowSizeSignal() to Page for reactive window size tracking
Commit · Pull requestAdds a read-only Signal to Page that automatically updates when the browser window is resized. Reuses the same JS resize listener infrastructure as addBrowserWindowResizeListener() via a shared ensureResizeListener() method.
Fixes
-
Revert invalid change
Commit · Pull request -
Remove git stash from pre-commit hook to prevent merge conflicts
Commit · Pull requestThe stash push/pop cycle caused merge conflicts when Spotless reformatted staged files, leaving the working tree in a broken state requiring manual resolution. The trade-off is that partial staging (git add -p) may now include unstaged formatting changes, which is cosmetic and recoverable.
-
Populate ActiveStyleSheetTracker during page load for CSS live reload without HotSwap Agent
Commit · Pull request · IssueActiveStyleSheetTracker was only populated by StyleSheetHotswapper.onInit(), which requires a HotSwap Agent. Without one, the tracker stayed empty and PublicResourcesLiveUpdater's file watcher silently skipped all CSS updates. Register active StyleSheet URLs during normal dev-mode page loading: - AppShellRegistry.createSettings() tracks AppShell stylesheets - UIInternals.addComponentDependencies() tracks component stylesheets Both paths are guarded by !isProductionMode() for zero production overhead. Also simplify the live reload integration test to rely on the file watcher instead of manually triggering reload via button clicks.
-
Allow signal.get() in Binder validators
Commit · Pull request · IssueSplit the conversion chain into executeConversionChain() (raw, used by the signal effect for dependency tracking) and doConversion() (always wrapped in untracked(), used by all other callers). Extract fireValidationEvents() so the effect can fire events directly. Guard trackUsageOfInternalValidationSignal() with isActive() to skip work inside untracked contexts.
-
IndexOutOfBoundsException when serializing arrays in JacksonSerializer
Commit · Pull request · IssueWhen serializing Java arrays, JacksonSerializer was using ArrayNode.set(i, value) on a newly created ArrayNode. In Jackson, set() expects an existing element at the given index, leading to an IndexOutOfBoundsException for new arrays. This change switches to ArrayNode.add(value) to correctly populate the array. Additionally, support for deserializing JSON arrays back into Java arrays was added to ensure symmetry in JacksonSerializer.
-
Update outer transaction read revision before publishing changes in StagedTransaction
Commit · Pull requestMove the outer.include() loop from commit() into commitTwoPhase(), between applyChanges() and publishChanges(). This ensures the outer RepeatableReadTransaction's read revision is updated before change listeners fire, so that downstream effects (like hasChanges()) can read the new value when signal.update() is used with a session-scoped fallback transaction.
Vaadin Flow 25.0.7
Changes since 25.0.6
Fixes
-
Populate ActiveStyleSheetTracker during page load for CSS live reload without HotSwap Agent (#23603)
Commit · Pull request · IssueActiveStyleSheetTracker was only populated by StyleSheetHotswapper.onInit(), which requires a HotSwap Agent. Without one, the tracker stayed empty and PublicResourcesLiveUpdater's file watcher silently skipped all CSS updates. Register active @Stylesheet URLs during normal dev-mode page loading: - AppShellRegistry.createSettings() tracks AppShell stylesheets - UIInternals.addComponentDependencies() tracks component stylesheets Both paths are guarded by !isProductionMode() for zero production overhead. Also simplify the live reload integration test to rely on the file watcher instead of manually triggering reload via button clicks.
-
IndexOutOfBoundsException when serializing arrays in JacksonSerializer (#23600)
Commit · Pull request · IssueWhen serializing Java arrays, JacksonSerializer was using ArrayNode.set(i, value) on a newly created ArrayNode. In Jackson, set() expects an existing element at the given index, leading to an IndexOutOfBoundsException for new arrays. This change switches to ArrayNode.add(value) to correctly populate the array. Additionally, support for deserializing JSON arrays back into Java arrays was added to ensure symmetry in JacksonSerializer.
-
Use raw request URI for baseHref calculation to support encoded slashes (#23569) (CP: 25.0)
Commit · Pull request · IssueThe previous fix for encoded slashes (%2F) in wildcard route parameters (commit b0c121b) set urlPathHelper.setUrlDecode(false) in ForwardingRequestWrapper, which made getPathInfo() return percent-encoded paths for all requests. This broke static resource serving for files with spaces in their names and potentially affected other getPathInfo() consumers like DAUUtils. Instead of disabling URL decoding globally, fix the actual site where the raw path matters: BootstrapHandlerHelper.getServiceUrl(). This method uses getCancelingRelativePath() to count path segments for the baseHref, which must use the raw URI so that %2F is not mistaken for a real path separator. The fix computes the raw path info by stripping the context path and servlet path from the request URI, preserving the original encoding. This allows reverting setUrlDecode(false) so that getPathInfo() returns properly decoded paths for all consumers. The 25.0 branch does not have JUnit 6 as a dependency, so the cherry-picked test class fails to compile. Convert to JUnit 4 imports and make the class and test methods public.
-
Restore backwards-compatible 2-parameter constructors for BlurEvent and FocusEvent (#23500)
Commit · Pull requestThe 3-parameter constructors with @eventdata broke backwards compatibility for code that directly instantiates these events. Re-add the original (Component, boolean) constructors alongside the @eventdata variants, matching the pattern used by ClickEvent, KeyDownEvent, etc.
-
Update tailwind path (#23481)
Commit · Pull request · IssueMake the tailwind template import target not ./ but from Frontend so we do not get faulty imports in generated.
-
Prevent NPE in ShortcutRegistration when lifecycleOwner is null (#23465)
Commit · Pull request · IssueAdd null guard in fireShortcutEvent() to handle the case where a KeyDown event fires after the shortcut's lifecycle owner has been detached and remove() has set lifecycleOwner to null.
-
Detect theme component CSS changes even without theme.json (#23452)
Commit · Pull request · IssuethemeShadowDOMStylesheetsChanged only scanned for components/ folders in themes discovered via theme.json. Themes without a theme.json (but with a components/ directory) were silently skipped, so the dev bundle was never rebuilt to include their component styles. Always include the main theme name when scanning for components/ folders, regardless of whether theme.json exists.
-
Set required Java and Maven versions in flow-maven-plugin (#23434)
Commit · Pull requestPrevents potential issues with Maven versions >= 3.9.12 if a Java version newer than the supported one is used to package the Maven plugin.
-
Pass javaResourceFolder to Options in DevModeInitializer (#23440) (CP: 25.0)
Commit · Pull request · IssueDevModeInitializer was creating an Options object without setting javaResourceFolder, causing TaskUpdateSettingsFile to overwrite it with an empty string. This broke legacy theme component styles in Gradle dev mode because the Vite theme plugin couldn't find vaadin-featureflags.properties in the correct location.
-
Remove Content-Type header from heartbeat requests and responses (#23225)
Commit · Pull request · IssueHeartbeat requests and responses both have empty bodies, so the with Web Application Firewalls (WAFs). WAFs struggle to validate text/plain requests with no body content, triggering false positive security alerts in SOC monitoring systems. Changes: - Server: Remove Content-Type header from successful heartbeat responses in HeartbeatHandler (empty body = no content type needed) - Client: Remove Content-Type from heartbeat POST requests in Heartbeat.java (request body is null) - Tests: Add verification that Content-Type is not set while Cache-Control remains in place The original Content-Type header was added in 2013 to fix Firefox issue vaadin/framework#4167, where Firefox tried to parse the empty response as HTML and threw errors. This is no longer relevant because: 1. Vaadin's client code never reads the response body, avoiding any parsing that would trigger browser errors 2. Modern browsers handle empty responses without Content-Type 3. HTTP best practices recommend no Content-Type for empty bodies The Cache-Control: no-cache header is retained as it's still required for iOS 6 Safari compatibility (vaadin/framework#3226).
Vaadin Flow 24.9.13
Changes since 24.9.12
Fixes
-
Use raw request URI for baseHref calculation to support encoded slashes (#23569) (#23572)
Commit · Pull request · IssueThe previous fix for encoded slashes (%2F) in wildcard route parameters (commit b0c121b) set urlPathHelper.setUrlDecode(false) in ForwardingRequestWrapper, which made getPathInfo() return percent-encoded paths for all requests. This broke static resource serving for files with spaces in their names and potentially affected other getPathInfo() consumers like DAUUtils. Instead of disabling URL decoding globally, fix the actual site where the raw path matters: BootstrapHandlerHelper.getServiceUrl(). This method uses getCancelingRelativePath() to count path segments for the baseHref, which must use the raw URI so that %2F is not mistaken for a real path separator. The fix computes the raw path info by stripping the context path and servlet path from the request URI, preserving the original encoding. This allows reverting setUrlDecode(false) so that getPathInfo() returns properly decoded paths for all consumers.
-
Restore backwards-compatible 2-parameter constructors for BlurEvent and FocusEvent (#23500)
Commit · Pull requestThe 3-parameter constructors with @eventdata broke backwards compatibility for code that directly instantiates these events. Re-add the original (Component, boolean) constructors alongside the @eventdata variants, matching the pattern used by ClickEvent, KeyDownEvent, etc.
-
Handle BaseJsonNode type in WebComponentGenerator JS type mapping (#23489)
Commit · Pull request · IssueUse BaseJsonNode.class.isAssignableFrom() in getJSTypeName() to match the approach already used in getDefaultJsValue(), so that properties added via addProperty with a Jackson ObjectNode default value are correctly mapped to the "Object" JS type.
-
Prevent NPE in ShortcutRegistration when lifecycleOwner is null (#23465)
Commit · Pull request · IssueAdd null guard in fireShortcutEvent() to handle the case where a KeyDown event fires after the shortcut's lifecycle owner has been detached and remove() has set lifecycleOwner to null.
-
Set required Java and Maven versions in flow-maven-plugin (#23435)
Commit · Pull requestPrevents potential issues with Maven versions >= 3.9.12 if a Java version newer than the supported one is used to package the Maven plugin.