-
Notifications
You must be signed in to change notification settings - Fork 10
Migrate to DownloadHandler API for Vaadin 25 compatibility #189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mlopezFC
wants to merge
3
commits into
master
Choose a base branch
from
issue-179
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,190 @@ | ||
| # Migration Guide: StreamResource to DownloadHandler | ||
|
|
||
| ## Overview | ||
|
|
||
| Starting with version 2.6.0, Grid Exporter Add-on introduces new `DownloadHandler`-based methods to replace the deprecated `StreamResource` methods. This migration is necessary for forward compatibility: as of Vaadin 25, `StreamResource` is deprecated and marked for removal, and it will be removed in a future Vaadin release. | ||
|
|
||
| ## What's Changing? | ||
|
|
||
| The Grid Exporter Add-on now provides two sets of methods: | ||
|
|
||
| - **Old API (Deprecated)**: Methods returning `StreamResource` or `GridExporterStreamResource` | ||
| - **New API (Recommended)**: Methods returning `DownloadHandler` | ||
|
|
||
| ## Backward Compatibility | ||
|
|
||
| ✅ **Your existing code will continue to work!** The old methods are deprecated but still functional. You can migrate at your own pace. | ||
|
|
||
| ## Migration Steps | ||
|
|
||
| ### 1. Update Vaadin Version | ||
|
|
||
| The new `DownloadHandler` API requires **Vaadin 24.8.0 or later**. | ||
|
|
||
| **pom.xml:** | ||
| ```xml | ||
| <properties> | ||
| <vaadin.version>24.8.0</vaadin.version> | ||
| </properties> | ||
| ``` | ||
|
|
||
| ### 2. Update Method Calls | ||
|
|
||
| Replace the deprecated `get*StreamResource()` methods with the new `get*DownloadHandler()` methods. | ||
|
|
||
| #### Excel Export | ||
|
|
||
| **Before:** | ||
| ```java | ||
| Anchor excelLink = new Anchor("", FontAwesome.Regular.FILE_EXCEL.create()); | ||
| excelLink.setHref(exporter.getExcelStreamResource()); | ||
| excelLink.getElement().setAttribute("download", true); | ||
| ``` | ||
|
|
||
| **After:** | ||
| ```java | ||
| Anchor excelLink = new Anchor("", FontAwesome.Regular.FILE_EXCEL.create()); | ||
| excelLink.setHref(exporter.getExcelDownloadHandler()); | ||
| excelLink.getElement().setAttribute("download", true); | ||
| ``` | ||
|
|
||
| #### DOCX Export | ||
|
|
||
| **Before:** | ||
| ```java | ||
| exporter.getDocxStreamResource() | ||
| exporter.getDocxStreamResource(customTemplate) | ||
| ``` | ||
|
|
||
| **After:** | ||
| ```java | ||
| exporter.getDocxDownloadHandler() | ||
| exporter.getDocxDownloadHandler(customTemplate) | ||
| ``` | ||
|
|
||
| #### PDF Export | ||
|
|
||
| **Before:** | ||
| ```java | ||
| exporter.getPdfStreamResource() | ||
| exporter.getPdfStreamResource(customTemplate) | ||
| ``` | ||
|
|
||
| **After:** | ||
| ```java | ||
| exporter.getPdfDownloadHandler() | ||
| exporter.getPdfDownloadHandler(customTemplate) | ||
| ``` | ||
|
|
||
| #### CSV Export | ||
|
|
||
| **Before:** | ||
| ```java | ||
| exporter.getCsvStreamResource() | ||
| ``` | ||
|
|
||
| **After:** | ||
| ```java | ||
| exporter.getCsvDownloadHandler() | ||
| ``` | ||
|
|
||
| ### 3. Update Custom Export Links (if applicable) | ||
|
|
||
| If you're creating custom export links instead of using auto-attached buttons: | ||
|
|
||
| **Before:** | ||
| ```java | ||
| GridExporter<Person> exporter = GridExporter.createFor(grid); | ||
| exporter.setAutoAttachExportButtons(false); | ||
|
|
||
| Anchor customLink = new Anchor("", "Download Excel"); | ||
| customLink.setHref(exporter.getExcelStreamResource().forComponent(customLink)); | ||
| ``` | ||
|
|
||
| **After:** | ||
| ```java | ||
| GridExporter<Person> exporter = GridExporter.createFor(grid); | ||
| exporter.setAutoAttachExportButtons(false); | ||
|
|
||
| Anchor customLink = new Anchor("", "Download Excel"); | ||
| customLink.setHref(exporter.getExcelDownloadHandler().forComponent(customLink)); | ||
| ``` | ||
|
|
||
| > **Note:** `forComponent(...)` is optional. It binds the download to a component so that the component is automatically disabled while the export runs (when `setDisableOnClick(true)` is enabled). If you don't need that behavior, you can omit it: `customLink.setHref(exporter.getExcelDownloadHandler());` | ||
|
|
||
| ## API Comparison | ||
|
|
||
| | Old Method (Deprecated) | New Method | Notes | | ||
| |------------------------|------------|-------| | ||
| | `getExcelStreamResource()` | `getExcelDownloadHandler()` | Excel export | | ||
| | `getExcelStreamResource(String)` | `getExcelDownloadHandler(String)` | Excel with template | | ||
| | `getDocxStreamResource()` | `getDocxDownloadHandler()` | DOCX export | | ||
| | `getDocxStreamResource(String)` | `getDocxDownloadHandler(String)` | DOCX with template | | ||
| | `getPdfStreamResource()` | `getPdfDownloadHandler()` | PDF export | | ||
| | `getPdfStreamResource(String)` | `getPdfDownloadHandler(String)` | PDF with template | | ||
| | `getCsvStreamResource()` | `getCsvDownloadHandler()` | CSV export | | ||
|
|
||
| ## Features Preserved | ||
|
|
||
| All existing features continue to work with the new API: | ||
|
|
||
| - ✅ Concurrent download control | ||
| - ✅ Download timeouts | ||
| - ✅ Button disable/enable during download | ||
| - ✅ Custom templates | ||
| - ✅ All export formats (Excel, DOCX, PDF, CSV) | ||
| - ✅ Custom columns and headers | ||
| - ✅ Hierarchical data support | ||
|
|
||
| ## Timeline | ||
|
|
||
| - **Version 2.6.0**: New `DownloadHandler` methods introduced, old methods deprecated | ||
| - **Version 3.0.0**: Old `StreamResource` methods will be removed | ||
|
|
||
| ## Need Help? | ||
|
|
||
| If you encounter any issues during migration, please: | ||
| 1. Check that you're using Vaadin 24.8.0 or later | ||
| 2. Review the deprecation warnings in your IDE | ||
| 3. Open an issue on [GitHub](https://github.com/FlowingCode/GridExporterAddon/issues) | ||
|
|
||
| ## Example: Complete Migration | ||
|
|
||
| **Before (Version 2.5.x):** | ||
| ```java | ||
| Grid<Person> grid = new Grid<>(Person.class); | ||
| grid.setItems(people); | ||
|
|
||
| GridExporter<Person> exporter = GridExporter.createFor(grid); | ||
| // Auto-attached buttons use StreamResource internally | ||
| ``` | ||
|
|
||
| **After (Version 2.6.0+):** | ||
| ```java | ||
| Grid<Person> grid = new Grid<>(Person.class); | ||
| grid.setItems(people); | ||
|
|
||
| GridExporter<Person> exporter = GridExporter.createFor(grid); | ||
| // Auto-attached buttons now use DownloadHandler internally | ||
| // No code changes needed if using auto-attached buttons! | ||
| ``` | ||
|
|
||
| **Custom Implementation:** | ||
| ```java | ||
| Grid<Person> grid = new Grid<>(Person.class); | ||
| grid.setItems(people); | ||
|
|
||
| GridExporter<Person> exporter = GridExporter.createFor(grid); | ||
| exporter.setAutoAttachExportButtons(false); | ||
|
|
||
| // Create custom export buttons | ||
| Anchor excelBtn = new Anchor("", "Excel"); | ||
| excelBtn.setHref(exporter.getExcelDownloadHandler()); | ||
| excelBtn.getElement().setAttribute("download", true); | ||
|
|
||
| Anchor pdfBtn = new Anchor("", "PDF"); | ||
| pdfBtn.setHref(exporter.getPdfDownloadHandler()); | ||
| pdfBtn.getElement().setAttribute("download", true); | ||
|
|
||
| add(excelBtn, pdfBtn); | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
src/main/java/com/flowingcode/vaadin/addons/gridexporter/ConcurrentDownloadHandler.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| /*- | ||
| * #%L | ||
| * Grid Exporter Add-on | ||
| * %% | ||
| * Copyright (C) 2022 - 2024 Flowing Code | ||
| * %% | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| * #L% | ||
| */ | ||
| package com.flowingcode.vaadin.addons.gridexporter; | ||
|
|
||
| import com.vaadin.flow.server.streams.DownloadHandler; | ||
| import com.vaadin.flow.server.streams.DownloadEvent; | ||
| import java.io.IOException; | ||
| import java.io.InterruptedIOException; | ||
| import java.nio.channels.InterruptedByTimeoutException; | ||
|
|
||
| /** | ||
| * An implementation of {@link DownloadHandler} that controls access to the | ||
| * {@link #handleDownloadRequest(DownloadEvent) handleDownloadRequest} method | ||
| * using a semaphore to | ||
| * manage concurrency. | ||
| * | ||
| * @author Javier Godoy | ||
| */ | ||
| @SuppressWarnings("serial") | ||
| abstract class ConcurrentDownloadHandler extends ConcurrentOperationBase implements DownloadHandler { | ||
|
|
||
| private final DownloadHandler delegate; | ||
|
|
||
| /** | ||
| * Constructs a {@code ConcurrentDownloadHandler} with the specified delegate. | ||
| * The delegate is a | ||
| * {@link DownloadHandler} that performs the actual download handling. | ||
| * | ||
| * @param delegate the delegate {@code DownloadHandler} | ||
| */ | ||
| ConcurrentDownloadHandler(DownloadHandler delegate) { | ||
| this.delegate = delegate; | ||
| } | ||
|
|
||
| /** | ||
| * Handles the download request using the provided {@link DownloadEvent}. | ||
| * <p> | ||
| * Note that the method is not called under the session lock. It means that if | ||
| * implementation | ||
| * requires access to the application/session data then the session has to be | ||
| * locked explicitly. | ||
| * <p> | ||
| * If a semaphore has been set, it controls access to this method, enforcing a | ||
| * timeout. A permit | ||
| * will be acquired from the semaphore, if one becomes available within the | ||
| * given waiting time and | ||
| * the current thread has not been {@linkplain Thread#interrupt interrupted}. | ||
| * | ||
| * @param event the download event containing the output stream and session | ||
| * @throws IOException if an IO error occurred | ||
| * @throws InterruptedIOException if the current thread is interrupted | ||
| * @throws InterruptedByTimeoutException if the waiting time elapsed before a | ||
| * permit was acquired | ||
| */ | ||
| @Override | ||
| public final void handleDownloadRequest(DownloadEvent event) throws IOException { | ||
| runWithSemaphore(event.getSession(), () -> delegate.handleDownloadRequest(event)); | ||
| } | ||
|
|
||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.