Powrót do strony głównej

Modułowa biblioteka jasper-modular dla JasperReports

Biblioteka jasper-modular upraszcza pracę z subraportami w JasperReports dzięki typizowanym klasom Java i adnotacjom. Automatyczna generacja JRXML i parametrów eliminuje ręczne wiercenie w danych. Wspiera zagnieżdżanie i kolekcje dla złożonych raportów.

jasper-modular: modułowe raporty w JasperReports bez bólu
Advertisement 728x90

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:

Google AdInline article slot
  • <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:

Google AdInline article slot
<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:

Google AdInline article slot
@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

Advertisement 728x90

Czytaj dalej