Modularna biblioteka dla JasperReports: uproszczenie subraportów i danych
Praca z dużymi raportami w JasperReports prowadzi do monolitowych plików JRXML. Projekt, logika danych i reguły biznesowe mieszają się, utrudniając utrzymanie. Subraporty rozwiązują problem modularności, ale przekazywanie danych do nich sprawia trudności.
Typowe podejścia do danych:
- Pojedynczy JSON: JsonDataSource ze ścieżkami w XML. Błędy w ścieżkach nie są wykrywane podczas kompilacji, REPORT_DATA_SOURCE jest przekazywany niejawnie.
- SQL w szablonie: REPORT_CONNECTION dla zapytań. Logika poza Javą, bez sprawdzania typów.
- Przekazywanie REPORT_DATA_SOURCE: Consumable-data source wyczerpuje się po pierwszym subrapocie.
- Ręczne parametry: Dziesiątki <subreportParameter> i params.put() w Javie, wymagające synchronizacji.
Zasada jasper-modular
Biblioteka przekazuje do każdego subraportu dwa parametry:
<prefix>Report— skompilowany JasperReport.<prefix>MapParameter— Map<String, Object> z danymi.
Map jest rozpakowywana przez REPORT_PARAMETERS_MAP: klucze stają się $P{key} bez <subreportParameter>. Procesor adnotacji generuje parametry i JRXML podczas kompilacji. Renderer rekurencyjnie wypełnia subraporty przez refleksję.
Podłączanie zależności
Dla JasperReports 7.x:
<dependency>
<groupId>io.github.hhdevr</groupId>
<artifactId>jasper-modular-starter-jr7</artifactId>
<version>1.0.0</version>
</dependency>
Dla 6.x:
<dependency>
<groupId>io.github.hhdevr</groupId>
<artifactId>jasper-modular-starter-jr6</artifactId>
<version>1.0.0</version>
</dependency>
Procesor adnotacji w maven-compiler-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.github.hhdevr</groupId>
<artifactId>jasper-modular-processor-jr7</artifactId>
<version>1.0.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
Struktura klas raportu
Raport główny:
@Getter
@Setter
@JasperModularReport(templatePath = "/reports/company_report.jrxml")
public class CompanyReport extends ModularReport {
private TitleSubModule titleSubModule;
private FinancialSubModule financialSubModule;
}
Subraport:
@Getter
@Setter
@JasperSubreport(templatePath = "/reports/sub_title_report.jrxml", prefix = "Title")
public class TitleSubModule extends SubreportModule {
private CompanyDetails companyDetails;
private String period;
private String currency;
@Override
public boolean isEmpty() {
return companyDetails == null;
}
}
Zagnieżdżenie: FinancialSubModule zawiera RevenueSubModule, ExpenseSubModule, ProfitSubModule. Każdy moduł sprawdza isEmpty() dla warunkowego renderowania.
Kolekcje:
@JasperCollection(columnWidth = 150)
private List<RevenueItem> items;
Wykluczanie pól:
@JasperIgnore
private transient String internalCache;
Tryby generowania JRXML
Procesor adnotacji aktualizuje szablony w target/generated-sources/:
- CREATE: Tworzy pełny JRXML z parametrami, zestawami danych, komponentami kolekcji i pasami subraportów.
- INJECT (domyślnie): Dodaje brakujące elementy, zachowując istniejący projekt.
- NONE: Bez zmian.
Po generacji szablony są dopracowywane w Jaspersoft Studio.
Drzewo przykładowego projektu:
- CompanyReport
- TitleSubModule (CompanyDetails, period, currency)
- FinancialSubModule
- RevenueSubModule (totalRevenue, growthPercent, List<RevenueItem>)
- ExpenseSubModule (totalExpenses, growthPercent, List<ExpenseItem>)
- ProfitSubModule (grossProfit, operatingProfit, netProfit, margin, List<ProfitBreakdown>)
Co jest ważne
- Modularność przez klasy Java: subraporty jako pola, dane są typowane.
- Automatyczne generowanie parametrów i JRXML przez procesor adnotacji.
- Rekurencyjny render bez ręcznego przekazywania danych.
- Obsługa kolekcji z @JasperCollection i zagnieżdżenia dowolnej głębokości.
- Kompatybilność z JasperReports 6.x/7.x i Spring Boot 3.x/4.x.
— Editorial Team
Brak komentarzy.