Skip to content

Releases: vaadin/flow

Vaadin Flow 25.1.0-beta3

12 Mar 12:18
0908eaa

Choose a tag to compare

Pre-release

Changes since 25.1.0-beta2

All changes

Breaking changes

  • Make localeSignal() read-only on VaadinSession and UI (#23828)
    Commit · Pull request

    Return 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 request

    Previously, the computed method 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 separate cached method that creates a cached signal out of any other signal. signals

New features

  • Apply ElementEffect once when created (#23824)
    Commit · Pull request · Issue

    ElementEffect 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 · Issue

    Add 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 · Issue

    During 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 request

    AbstractUpdateImports.process() already reorders import lines to the top for generatedFlowImports, but the same sorting was not applied to generatedFlowWebComponentImports. This caused interleaved import and non-import lines (e.g. injectGlobalWebcomponentCss() calls mixed with import statements) in the web component output. Extract a reusable moveImportsToTop() method and apply it both in process() for main imports and in mergeWebComponentOutputLines() after merging and deduplicating the web component sources. Related to #23689 (comment)

  • Improve npm resolution for non-windows (#23810)
    Commit · Pull request

    Adds 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 request

    When 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 request

    Convert 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

12 Mar 14:55
81584ec

Choose a tag to compare

Pre-release

Changes since 24.10.0-alpha2

All changes

Fixes

  • Detect router-link attribute in ancestor elements during click navigation (#23786)
    Commit · Pull request

    When 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 · Issue

    Log instead of throwing when node_modules removal fails in cleanUp.

  • Clamp effectiveRequested range in DataCommunicator to prevent IndexOutOfBoundsException (#23672)
    Commit · Pull request · Issue

    When 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 · Issue

    The 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

09 Mar 16:32
45efe30

Choose a tag to compare

Changes since 25.0.7

All changes

Fixes

  • Detect router-link attribute in ancestor elements during click navigation (#23786)
    Commit · Pull request

    When 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 request

    When 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 · Issue

    Log instead of throwing when node_modules removal fails in cleanUp.

  • Clamp effectiveRequested range in DataCommunicator to prevent IndexOutOfBoundsException (#23672)
    Commit · Pull request · Issue

    When 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

Vaadin Flow 24.9.14

09 Mar 16:33
34d2faf

Choose a tag to compare

Changes since 24.9.13

All changes

Fixes

  • Detect router-link attribute in ancestor elements during click navigation (#23786) (#23800)
    Commit · Pull request

    When 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 · Issue

    Log instead of throwing when node_modules removal fails in cleanUp.

  • Clamp effectiveRequested range in DataCommunicator to prevent IndexOutOfBoundsException (#23672)
    Commit · Pull request · Issue

    When 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

09 Mar 09:00
3d4ef5a

Choose a tag to compare

Pre-release

Changes since 25.1.0-beta1

All changes

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 request

    All 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 · Issue

    This 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 to StyleSheet URLs so browsers reload only when file content changes, enabling aggressive caching with Cache-Control: max-age=31536000, immutable for versioned requests. - Content hashing is applied in both the AppShell path (AppShellRegistry.addStyleSheets) and the component dependency path (UidlWriter.dependencyToJson), covering all StyleSheet usage. - StaticFileServer now returns a 1-year immutable cache header when the v-c query parameter is present in production mode, instead of the default short-lived cache.

Fixes

  • Shared Signal.get() should throw outside reactive context with fallback transaction (#23760)
    Commit · Pull request · Issue

    The 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 · Issue

    The 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 · Issue

    Capture 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 request

    Supporting 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 request

    The 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 request

    The 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

Vaadin Flow 25.1.0-beta1

03 Mar 12:16
6e2f469

Choose a tag to compare

Pre-release

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 request

    Signals 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 request

    Simplified the signal API by removing the WritableSignal interface and consolidating functionality.

  • Rename Signal value()/value(T) to get()/set(T)
    Commit · Pull request

    Renamed 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 request

    The separate signals module has been merged into flow-server for better integration.

  • Rename Binder.Binding.value() to valueSignal() and return signal
    Commit · Pull request

    Reworks Binding.value() to return a ValueSignal instead of the raw value.

  • Rename getValidationStatus() to validationStatusSignal()
    Commit · Pull request

    Renames the Binder method to better reflect that it returns a Signal.

Component and API Changes

  • Make wrapperElement field private
    Commit · Pull request

    The 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 request

    The 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 · Issue

    Updated browser compatibility check to ensure Popover API availability, required for Vaadin 25 web components.

New Features

Signal-Based Reactive Programming

Component Signal Bindings

Read more

Vaadin Flow 25.1.0-alpha14

24 Feb 10:59
64e4c1c

Choose a tag to compare

Pre-release

Changes since 25.1.0-alpha13

All changes

New features

  • Use type-parameter-level nullability for Signal APIs
    Commit · Pull request

    Follow 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

24 Feb 09:06
c769cc1

Choose a tag to compare

Pre-release

Changes since 25.1.0-alpha12

All changes

Breaking changes

  • Enforce signal reads in computed signals and effects
    Commit · Pull request

    Help 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 · Issue

    Optimize 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 · Issue

    Signal.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 · Issue

    Shared 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 request

    Allow 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 request

    Adds 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 request

    The 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 · Issue

    ActiveStyleSheetTracker 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 · Issue

    Split 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 · Issue

    When 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 request

    Move 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

23 Feb 12:32
1cde734

Choose a tag to compare

Changes since 25.0.6

All changes

Fixes

  • Populate ActiveStyleSheetTracker during page load for CSS live reload without HotSwap Agent (#23603)
    Commit · Pull request · Issue

    ActiveStyleSheetTracker 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 · Issue

    When 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 · Issue

    The 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 request

    The 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 · Issue

    Make 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 · Issue

    Add 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 · Issue

    themeShadowDOMStylesheetsChanged 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 request

    Prevents 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 · Issue

    DevModeInitializer 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 · Issue

    Heartbeat 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

23 Feb 10:07
ec836e1

Choose a tag to compare

Changes since 24.9.12

All changes

Fixes

  • Use raw request URI for baseHref calculation to support encoded slashes (#23569) (#23572)
    Commit · Pull request · Issue

    The 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 request

    The 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 · Issue

    Use 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 · Issue

    Add 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 request

    Prevents potential issues with Maven versions >= 3.9.12 if a Java version newer than the supported one is used to package the Maven plugin.