Hi,
You’re suggesting that I shouldn’t use the Grid Export Action add‑on to handle this task (which I was using), and instead create my own export dialog and manually generate the CSV.
Yes. With data sets this large you’ll get better results if you implement your own exporter and tune it for performance and memory usage.
- Run the root task asynchronously, and make each sub‑task asynchronous as well.
- Pick a batch size that gives the best trade‑off between speed and RAM—about 1 000 – 5 000 rows is usually fine.
- Let every batch stream its chunk straight into the same file.
Typical optimisations: start one async thread that parallelises the queries; if the total record count is under ± 60 000 you can process it in a single pass, otherwise switch to a “super‑batch” pattern. After each batch is loaded, write it synchronously to disk. The exact strategy is up to you—decide whether you prefer the fastest download or the lowest resource usage.
You can also plug in a custom exporter and override the default logic:
https://docs.jmix.io/jmix/grid-export/exporters.html
So, there’s no way to intercept the Grid Export Action event to check how many records the user wants to export and decide whether to limit it or not?
Yes, you can. Provide your own exported bean or create a new action that extends and overrides the existing one.
If there is a way to intercept the “export all” action, I could use that to trigger my own CSV generation logic.
Exactly—that’s the approach described above.
In the example you showed, where the CSV is generated via a service — should this be used from a custom REST endpoint, rather than a View and Controller?
If you want the logic to be reusable, then yes—put it in your own @Service
and call that service from the exporter (or expose it via REST if needed).
For reference, the source of the export add‑on is quite small and easy to follow:
Speed vs. complexity
Level |
How it works |
When to choose |
1 — Maximum speed (parallel fetch, ordered write) |
• In the async task, spawn several workers that fetch different batches in parallel. • Each worker puts its result into a concurrent map keyed by batch index. • A single writer thread pulls the batches 0, 1, 2… from the map in order and appends them to the file, so the final CSV stays sequential. → Fastest, but the code is the most complex (synchronisation, back‑pressure, error handling). |
Huge exports where end‑‑to‑‑end time really matters and you can invest in a more elaborate implementation. |
2 — Balanced (one async task, sequential batches) |
• One background thread. • Inside it, fetch batches of 1 000 – 5 000 rows sequentially and write each batch straight to the file (use BufferedWriter , CSVPrinter , etc.). • Very little RAM footprint, simpler code than level 1, still much lighter than the default add‑on. |
Most business scenarios: 100 k – 1 M rows, need to keep the server healthy but don’t require the absolute minimum runtime. |
3 — Quick & easy (built‑in exporter) |
Just use the stock Jmix Export action. For data sets up to ≈ 100 k rows it performs well enough and you get progress UI and translations for free. |
Admin‑only exports, occasional downloads, prototypes. Minimal effort. |
Conclusions
If you only run this once in a while and the file is under ~100 k lines, stick with the built‑in exporter.
If you need better memory usage and predictable times, implement level 2.
If users are waiting on a 600 k+ export every day, invest in level 1.
Choose the simplest option that meets your performance target — no point in over‑engineering if a buffered single‑thread export already gets the job done.