Documentation

Governed reporting, made natural for Spring Boot developers.

Build annotation-driven template reports or programmable SQL and Excel reports, then deliver them through one secure, durable, and observable lifecycle.

One path from idea to production.

Start with the platform model, choose a reporting path, build the report, secure delivery, configure operations, then run every sample from the demo cookbook.

Open the cookbook

Start Here

Start Here

Review these topics in order, or jump directly to the card you need.

What Report-Boot Is

One governed report lifecycle with two equally important developer experiences.

How it flows

1Choose a report style
2Describe data and policy
3ReportService.generate(...)
4Render with a provider
5Store order and content
6Download, email, and govern

Report-Boot is not an Excel wrapper. It is a Spring Boot reporting framework that gives every report a stable identity, validation, provider selection, storage, expiry, security, delivery, and governance lifecycle.

PathBest whenDeveloper writesReport-Boot owns
Annotation-basedA Java DTO naturally represents the reportAnnotations, fields, and a templateMapping, validation, provider selection, filename, policy, lifecycle
Programmable SQL/ExcelThe report is tabular, dynamic, large, or dashboard-likeTrusted SQL and fluent buildersParameters, streaming, columns, formulas, workbook structure, lifecycle
  • Both paths return the same GeneratedReport contract.
  • Both paths can use durable UUID orders, filesystem content, secure access tokens, email delivery, and rb_log governance.
  • Providers are replaceable modules; application controllers stay small.
  • The framework favors business names such as Total and Customer over A1 coordinates and renderer internals.

Executive Library Map

Fifteen focused modules, one report lifecycle, and no forced all-in dependency stack.

Report-Boot is a modular Spring Boot reporting platform. Start with Core + Starter, choose annotation/template providers or SQL/programmatic reporting, then add delivery, observability and design capabilities only where they create value.

LibraryRoleWhat it gives youChoose it when
report-boot-coreFoundationContracts, annotations, mapping, provider SPI, lifecycle APIEvery integration; no renderer by itself
report-boot-spring-boot-starterBootstrapAuto-configuration, storage, orders, tokens, governanceNormal Spring Boot applications
report-boot-jasperTemplate providerJRXML to PDFPixel-aware enterprise PDF estates
report-boot-jxlsTemplate providerDesigned XLSX template to populated workbookAnalyst-owned spreadsheet layouts
report-boot-birtTemplate providerRPTDESIGN to PDFExisting BIRT estates
report-boot-thymeleafTemplate providerHTML and print-ready HTMLWeb-native documents and browser printing
report-boot-sqlData engineTrusted SQL to a governed tabular definitionDynamic, parameterized, multi-sheet reports
report-boot-excelWorkbook engineTemplate-free XLSX, formulas, charts, slices, stylesCode-first workbooks and dashboards
report-boot-csvTabular providerSingle CSV or multi-sheet ZIPMachine-readable extracts
report-boot-emailDeliveryAttachments, templates, schedules, conditions, idempotencyManual and automated report delivery
report-boot-insights-apiObservability contractsEvents, log entries, sinks, dashboard DTOsCustom telemetry and control centers
report-boot-insights-spring-boot-starterObservability runtimeLogback capture, ring buffer, sink forwardingAutomatic library-log ingestion
report-boot-designerDefinition contractsDesigner JSON to executable SQL definitionVisual and low-code report builders
report-boot-aiDesign assistantSecured Gemini proxy for design/chat responsesAI-assisted definition authoring
report-boot-demoReference applicationRunnable APIs, templates, database, SMTP and PostmanLearning, verification and integration tests
Developer pathSmallest useful stackTypical expansion
Annotation PDFstarter + jasperemail + insights + JDBC orders
Annotation Excel templatestarter + jxlsemail + secure links
Annotation HTMLstarter + thymeleafemail templates + print-ready pages
Dynamic SQL exportstarter + sql + excel/csvdesigner + dashboards + insights
Visual/AI designdesigner + sql + excelai proxy + starter + governance
Custom providercorestarter auto-configuration + contract tests

Every module chapter below answers four questions: why would I install it, what does it own, how do I configure it, and which demo recipe proves it works.

Five-Minute Start

Install the starter, choose a provider, configure storage, then generate your first governed report.

How it flows

1Add starter + provider
2Place templates/resources
3Configure Report-Boot
4Create DTO or definition
5Call ReportService
6Return GeneratedReport
pom.xml
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-spring-boot-starter</artifactId>
  <version>0.1.0-MVP</version>
</dependency>

<!-- Add only the providers you use -->
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-jasper</artifactId>
  <version>0.1.0-MVP</version>
</dependency>
application.yml
report-boot:
  templates-path: classpath:/report-boot/report-templates
  default-output: PDF
  database:
    initialize-schema: true
    schema: public
    table-prefix: rb_
  orders:
    type: jdbc
  storage:
    type: filesystem
    content-root: target/report-boot/reports
  governance:
    enabled: true
    instance-name: billing-service
  security:
    enabled: true
    default-expiry-minutes: 30
    max-expiry-minutes: 1440
    watermark-enabled: true
    one-time-download-enabled: false

Use reportService.generate(dto) for annotation reports. Use reportService.generate(code, definition, parameters, output) for SQL/builder reports. That is the central simplicity of Report-Boot.

Choose Your Path

Start from the report your users expect, not from an engine name.

NeedChooseReason
Governed PDF from a Java DTOAnnotations + JasperSmall API surface with strong template control.
Existing designed workbookAnnotations + JXLSPreserve a business-authored Excel template.
Dynamic operational exportSQL + Dynamic ExcelNo template maintenance; column-name builders and streaming.
Interactive workbook dashboardSQL + Dynamic Excel dashboard contractsCharts, KPIs, filters, and connected slices.
Simple machine-readable extractSQL + CSVSame definition, lightweight output.
Browser or print pageAnnotations + ThymeleafHTML/CSS templates and print rules.
Existing BIRT portfolioAnnotations + BIRTReuse .rptdesign assets.
Visual JSON designDesigner + SQL + ExcelTrusted data-source references with designer-defined presentation.
ProviderEngineOutputTemplateUse it for
JasperJASPERPDF.jrxmlPixel-aware enterprise PDFs and mature report templates.
JXLSJXLSEXCEL.xlsxTemplate-based Excel where a business-owned workbook is the design.
Dynamic ExcelDYNAMIC_EXCELEXCELNo templateCode-first tables, formulas, slices, charts, dashboards, and large exports.
BIRTBIRTPDF.rptdesignExisting BIRT estates and BIRT-designed reports.
ThymeleafTHYMELEAFHTML.htmlWeb-native, email-friendly, and print-ready HTML.
CSVDYNAMIC_TABLECSVNo templatePortable tabular extracts; multi-sheet definitions become a ZIP.

Core Library

The provider-neutral heart: describe a report once, then let an installed provider render it.

Use report-boot-core when you need the public ReportService API, annotation model, report mapping, lifecycle contracts, or a custom provider. It intentionally does not render PDF, Excel, CSV, or HTML by itself.

How it flows

1Application DTO or definition
2ReportDataMapper
3ReportService
4ReportProvider lookup
5Renderer
6GeneratedReport
ContractDeveloper valueImplement it when
ReportServiceOne generate/download entry point independent of engineNormally consume the starter default
ReportProvider / ReportRendererPluggable engine and output selectionAdding a renderer or enterprise engine
ReportDataProviderSeparates data acquisition from renderingConnecting REST, NoSQL, GraphQL, or custom data
ReportOrderRepositoryTracks UUID, state, expiry and download claimsReplacing memory/JDBC lifecycle storage
ReportContentStoreStores bytes outside the lifecycle rowAdding S3, Azure Blob, GridFS, or another content store
TemplateResolverResolves classpath or external template assetsAdding a template registry or tenant-aware lookup
ReportSecurityManagerCentral access decision contractIntegrating application identity and policy
pom.xml
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-core</artifactId>
  <version>0.1.0-MVP</version>
</dependency>

For most applications, depend on the Spring Boot starter plus the providers you need. Depend directly on core when you are building an extension module or intentionally wiring every contract yourself.

Capability statusMeaning
RuntimeThe framework executes the behavior today.
Descriptor contractCore extracts stable metadata; a focused adapter must enforce it.
Declaration onlyThe annotation/API exists but automatic execution is not wired yet.

Spring Boot Starter

Production-minded defaults for discovery, storage, security, governance and provider wiring.

Add the starter to a consuming Spring Boot service, then add only the rendering/data modules that service needs. Beans remain override-friendly, so enterprise adapters can replace defaults without forking Report-Boot.

pom.xml
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-spring-boot-starter</artifactId>
  <version>0.1.0-MVP</version>
</dependency>
Starter responsibilityDefaultWhy/when to change
Provider discoverySelect by engine + outputInstall a provider module; replace only for custom routing
Report ordersMemory for simple use; JDBC when configuredUse JDBC for restarts and multiple instances
Report bytesFilesystem content storeUse a shared mount or custom store across instances
Template resolutionreport-boot.templates-pathPoint to classpath or external template assets
Governancerb_log when JDBC and governance are enabledKeep enabled when auditability matters
Secure tokensDisabled until configuredEnable for expiring email/browser links
Unavailable pageNeutral built-in HTMLReplace or redirect for application branding
Startup compilationOffEnable to fail deployment before invalid templates serve traffic
application.yml
report-boot:
  templates-path: classpath:/report-boot/report-templates
  default-output: PDF
  database:
    initialize-schema: true
    schema: public
    table-prefix: rb_
  orders:
    type: jdbc
  storage:
    type: filesystem
    content-root: target/report-boot/reports
  governance:
    enabled: true
    instance-name: billing-service
  security:
    enabled: true
    default-expiry-minutes: 30
    max-expiry-minutes: 1440
    watermark-enabled: true
    one-time-download-enabled: false

The durable split is deliberate: rb_report_order stores state and a storage reference, while the actual report bytes remain in ReportContentStore. This keeps the database governable without turning it into a file bucket.

The Governed Lifecycle

Generation is more than bytes: it is a durable, inspectable business operation.

How it flows

1Validate request
2Resolve descriptor/definition
3Authorize
4Render
5Persist content
6Persist rb_report_order
7Write rb_log
8Download or deliver
GeneratedReport.java
GeneratedReport report = reportService.generate(request);

report.getReportOrderUuid();
report.getFileName();
report.getContentType();
report.getContent();
report.getGeneratedAt();
report.getAccessToken();
report.getAccessTokenExpiresAt();

The UUID identifies report state; it is not the file itself. With JDBC orders and filesystem content, multiple application instances share expiry, one-time download state, token hash, download count, and storage location without storing report bytes in the database.

Annotation Quick Start

Turn a normal DTO into a governed report contract.

How it flows

1POST JSON
2Spring maps DTO
3Annotations describe report
4ReportService validates and renders
5Provider produces output
6API downloads file
InvoiceReportDto.java
@ReportTemplate(
    code = "invoice-basic",
    title = "Basic Invoice",
    templateFile = "classpath:/report-boot/report-templates/invoice-basic.jrxml",
    output = ReportOutput.PDF
)
@ReportEngineType(ReportEngine.JASPER)
@ReportSecured(watermark = true, expiryMinutes = 30)
@ReportFileName("invoice-${invoiceNumber}.pdf")
@ReportAccess(role = "ROLE_REPORT_ADMIN")
@ReportTitle("Invoice Report")
@ReportCategory("Billing")
public class InvoiceReportDto {
    @ReportField("invoiceNumber")
    @ReportRequired
    @ReportSensitive
    private String invoiceNumber;

    @ReportField("customerName")
    @ReportRequired
    private String customerName;

    @ReportField("invoiceDate")
    @ReportDateFormat("yyyy-MM-dd")
    private LocalDate invoiceDate;

    @ReportField("totalAmount")
    @ReportCurrency("USD")
    @ReportFormat(pattern = "#,##0.00")
    private BigDecimal totalAmount;

    @ReportTable("items")
    private List<InvoiceItemDto> items;
}
InvoiceReportController.java
@RestController
@RequestMapping("/api/reports/jasper/invoice")
class InvoiceReportController {
    private final ReportService reportService;

    @PostMapping("/download")
    ResponseEntity<byte[]> download(@RequestBody InvoiceReportDto request) {
        GeneratedReport report = reportService.generate(request);
        return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"" + report.getFileName() + "\"")
            .contentType(MediaType.parseMediaType(report.getContentType()))
            .body(report.getContent());
    }
}
curl
curl --location --request POST "http://localhost:8080/api/reports/jasper/invoice/download" \
  --header "Content-Type: application/json" \
  --data '{
  "invoiceNumber": "INV-2026-1001",
  "customerName": "Acme Corporation",
  "invoiceDate": "2026-07-13",
  "totalAmount": 499.00,
  "items": [
    {
      "itemName": "Report-Boot Enterprise License",
      "quantity": 1,
      "unitPrice": 499.00,
      "total": 499.00
    }
  ]
}' \
  --output "invoice.pdf"

Annotation Reference

Know which annotations execute today and which are extension contracts.

A professional framework must separate a declared annotation from implemented behavior. Runtime means the current libraries consume it. Descriptor contract means it is captured for governance or extension adapters but does not automatically perform the named enterprise behavior.

CategoryAnnotationsCurrent maturityPurpose
Template@ReportTemplate, @ReportEngineType, @ReportFileNameRuntimeSelect template, engine, output, and safe generated filename.
Catalog@ReportTitle, @ReportDescription, @ReportVersion, @ReportCategoryRuntime metadataDescribe reports for catalogs, logs, and tooling.
Mapping@ReportField, @ReportParameter, @ReportTable, @ReportIgnoreRuntimeMap Java fields to scalar values, parameters, and repeated rows.
Validation@ReportRequiredRuntimeReject incomplete requests before rendering.
Formatting@ReportFormat, @ReportDateFormat, @ReportCurrency, @ReportLocaleRuntime mappingPrepare display-ready values for providers.
Security@ReportSecured, @ReportAccess, @ReportSensitiveRuntimeExpiry, one-time download, access decision metadata, and masking.
Storage@ReportRetention, @ReportChecksumDescriptor contractCaptured for policies/extensions; verify your policy adapter before relying on enforcement.
Enterprise@ReportPolicy, @ReportTenantField, @ReportCache, @ReportArchiveDescriptor contractGoverned extension metadata, not automatic business behavior by itself.
Automation@ReportSchedule, @ReportWebhook, @ReportAsyncDescriptor contractCore metadata; email scheduling has its own implemented @ReportEmailJob runtime.
Operations@ReportAudit, @ReportMetrics, @ReportStartupCompileDescriptor/partial runtimeMetadata plus starter/provider behavior where a corresponding component is installed.
Testing@ReportPreviewDescriptor contractSample and validation metadata for preview tooling.
Email@ReportEmailJob, @ReportEmailConditionRuntime in report-boot-emailBean discovery, database sync, cron scheduling, conditions, idempotency, SMTP, and logs.
Email events@ReportEmailOnEvent, @ReportEmailOnSuccess, @ReportEmailOnFailureDeclaration onlyAPI surface exists; automatic event execution is not wired in the current runtime.

Templates and Fields

The DTO is the bridge between your API model and provider template.

AnnotationPlace it onMeaning
@ReportTemplateClassStable code, display title, template resource, and output.
@ReportEngineTypeClassRenderer selected from the provider registry.
@ReportFileNameClassExpression such as invoice-${invoiceNumber}.pdf.
@ReportFieldFieldScalar template key; value defaults to the field mapping contract.
@ReportParameterFieldProvider/report parameter rather than ordinary detail data.
@ReportTableCollection fieldNamed repeatable dataset such as items.
@ReportRequiredFieldFails before renderer invocation when absent.
@ReportIgnoreFieldExcludes internal fields from mapped report data.
Resource layout
src/main/resources/
  report-boot/
    report-templates/
      invoice-basic.jrxml
      invoice-basic.xlsx
      invoice-basic.rptdesign
      invoice-thymeleaf.html
    email-templates/
      invoice-report-ready.html
    sql/
      invoice-dashboard.sql

Security, Expiry, and Access

A report policy follows the generated order across application instances.

How it flows

1@ReportSecured policy
2Create durable order
3Optionally issue signed token
4Validate UUID + token + expiry
5Atomically claim one-time download
6Return file or friendly unavailable page
Secure DTO
@ReportSecured(
    watermark = true,
    expiryMinutes = 5,
    oneTimeDownload = true
)
@ReportAccess(role = "ROLE_REPORT_ADMIN")
class ExternalInvoiceReport { ... }
  • expiryMinutes sets the durable rb_report_order.expires_at timestamp and caps the access-token expiry.
  • oneTimeDownload rejects a second successful claim and is suitable for external email links.
  • The signed token contains report identity and expiry; the database stores only token_id_hash, not the raw token.
  • Configure a SecurityProvider/ReportSecurityPolicy appropriate for your authentication model before treating role metadata as complete authorization.

Template Providers

Template Providers

Review these topics in order, or jump directly to the card you need.

Provider Guide

Change the provider without changing the core generation lifecycle.

ProviderDependencyEnable/configureDemo endpoint
Jasperreport-boot-jasperreport-boot.renderer.jasper.*/api/reports/jasper/invoice
JXLSreport-boot-jxlsreport-boot.renderer.jxls.*/api/reports/jxls/invoice
BIRTreport-boot-birtreport-boot.renderer.birt.*/api/reports/birt/invoice
Thymeleafreport-boot-thymeleaf + thymeleaf runtimereport-boot.renderer.thymeleaf.*/api/reports/thymeleaf/invoice

All annotation provider demos expose the same useful lifecycle: POST to generate metadata and UUID, POST /download for immediate output, and GET /{uuid}/download for a previously generated report.

Jasper Provider

Render annotation-driven DTOs through JRXML into mature, structured PDF output.

Choose Jasper when the organization owns JRXML templates or needs mature, pixel-aware PDF layouts. Developers define data and policy in Java; report designers own the JRXML presentation.

pom.xml
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-jasper</artifactId>
  <version>0.1.0-MVP</version>
</dependency>
application.yml
report-boot:
  renderer:
    jasper:
      enabled: true
      templates-path: classpath:/report-boot/report-templates
      cache-compiled-templates: true
  compilation:
    compile-on-startup: false
    fail-on-startup-error: true
    startup-threads: 0
Method/APIWhenResult
POST /api/reports/jasper/invoiceCreate lifecycle metadata first201 + reportOrderUuid
GET /api/reports/jasper/invoice/{uuid}/downloadDownload an existing orderPDF bytes
POST /api/reports/jasper/invoice/downloadOne-step browser/Postman flowImmediate PDF attachment
compile-on-startupDeployment should fail on bad JRXMLPrecompiled/warmed templates

JXLS Provider

Populate a business-designed XLSX template while keeping Java focused on data.

Choose JXLS when analysts or report designers maintain the workbook layout, merged cells, branding and fixed chart positions. Choose Dynamic Excel when code should generate the workbook structure instead.

pom.xml
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-jxls</artifactId>
  <version>0.1.0-MVP</version>
</dependency>
application.yml
report-boot:
  renderer:
    jxls:
      enabled: true
      content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
      throw-template-exceptions: true
FeatureUse it for
Prepared .xlsx templateBusiness-controlled layout and workbook art direction
Annotation DTO mappingScalar fields and repeated table rows
JxlsDesignerTemplateCompilerCompile supported visual-designer definitions into template structures
throw-template-exceptionsKeep true while developing so template faults are visible

BIRT Provider

Bring RPTDESIGN assets into the same governed ReportService lifecycle.

Choose BIRT when the organization already standardizes on BIRT templates and runtime behavior. The module is conditionally active only when its engine classes are present and the provider is enabled.

pom.xml
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-birt</artifactId>
  <version>0.1.0-MVP</version>
</dependency>
application.yml
report-boot:
  renderer:
    birt:
      enabled: true
      templates-path: classpath:/report-boot/report-templates
      cache-compiled-templates: true
      content-type: application/pdf
ChooseWhen
BIRTYou own .rptdesign assets and BIRT is an enterprise standard
JasperYou own .jrxml assets
ThymeleafHTML is the real output
Excel/JXLSSpreadsheet interaction is the deliverable

Thymeleaf Provider

Render annotation-driven reports as HTML for web, email-friendly and print-ready experiences.

Use Thymeleaf when markup and CSS are the natural report design tools. Normal HTML and A4 print-ready templates share the same DTO mapping, security and lifecycle behavior.

pom.xml
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-thymeleaf</artifactId>
  <version>0.1.0-MVP</version>
</dependency>
application.yml
report-boot:
  renderer:
    thymeleaf:
      enabled: true
      templates-path: classpath:/report-boot/report-templates
      encoding: UTF-8
      content-type: text/html;charset=UTF-8
      template-mode: HTML
Demo endpointPurpose
POST /api/reports/thymeleaf/invoice/downloadImmediate HTML invoice
POST /api/reports/thymeleaf/print-invoice/downloadA4 print-ready HTML
GET /api/reports/thymeleaf/invoice/{uuid}/downloadExisting governed order

Template Authoring

Keep report contracts stable while presentation assets evolve independently.

Place report templates under classpath:/report-boot/report-templates by default. A report DTO exposes provider-neutral field/table names; the selected template consumes those public names.

AssetProviderAuthoring rule
.jrxmlJasperDeclare fields matching @ReportField and data-source/table names matching @ReportTable
.xlsxJXLSUse JXLS expressions/areas and keep workbook layout business-owned
.rptdesignBIRTMatch report parameters/data bindings to mapped names
.htmlThymeleafUse mapped scalars and collections in normal Thymeleaf expressions
No assetDynamic Excel/CSVDefine layout and output in Java builders
Resource convention
src/main/resources/
└── report-boot/
    ├── report-templates/
    │   ├── invoice.jrxml
    │   ├── invoice.xlsx
    │   ├── invoice.rptdesign
    │   └── invoice.html
    ├── email-templates/
    ├── sql/
    └── download-pages/

Use startup compilation for template-backed providers when a broken asset should block deployment. Keep it off for the fastest local startup, then enable it in CI or production profiles.

Build a Provider

Extend Report-Boot without coupling core to a rendering engine.

How it flows

1Create provider module
2Depend on core
3Implement provider/renderer contracts
4Add conditional auto-configuration
5Back it with contract tests
6Install beside starter
RuleReason
Provider depends on core; core never depends on providerPreserves clean dependency direction
Use structured ReportDefinition/ReportDataAvoids provider-specific maps leaking into application code
Activate conditionally by class and propertyA missing optional engine must not break startup
Allow bean overrideConsumers can integrate enterprise storage/security
Report engine + output support explicitlyReportService can make deterministic choices
Test mapping, render, errors and auto-configurationA provider is a lifecycle participant, not only a byte generator
Custom data provider
@Component
class CustomerApiDataProvider implements ReportDataProvider {
    @Override
    public ReportData load(ReportDefinition definition, Map<String, Object> parameters) {
        // Fetch from a trusted API, then return provider-neutral report data.
        return ReportData.builder().values(loadCustomers(parameters)).build();
    }
}

SQL Library

Turn trusted SQL into a governed, parameterized report definition that Excel or CSV can render.

SQL owns data acquisition, parameters, row limits, timeouts, tenant enforcement, sorting and sheet composition. It does not decide the XLSX or CSV presentation. That separation lets one SqlReportDefinition produce either output.

pom.xml
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-sql</artifactId>
  <version>0.1.0-MVP</version>
</dependency>
Builder/configWhen to useWhy it matters
sqlFile(...) / sql(...)Select a trusted queryKeep request input out of SQL structure
parameters/defaultParametersBind dates, tenant and filtersUses named JDBC parameters instead of string concatenation
maxRowsEvery externally triggered reportPrevents accidental unbounded extracts
queryTimeoutSecondsQueries can stallStops database work after the agreed budget
fetchSizeLarge result setsEncourages streaming-friendly JDBC behavior
sortByStable output/group orderSorts by public column names before rendering
groupByRepeated department/customer sectionsRepeats headers and isolates group summaries
betweenGroupSpaceRowsGrouped Excel readabilityDefaults to three rows; set explicitly when layout is dense
tenant.column + tenant.parameter-nameMulti-tenant databasesEnforces tenant scope in the SQL execution path
InvoiceReports.java
SqlReportSheet invoices = SqlReportSheet.builder()
    .sheetName("Invoices")
    .sqlFile("invoice-report.sql")
    .sortBy("Created On", "Invoice No")
    .excel(excel -> excel
        .header(style -> style
            .backgroundColor(ExcelColors.Section.HEADER_BACKGROUND)
            .fontColor(ExcelColors.Section.HEADER_TEXT)
            .bold(true))
        .column("Customer", column -> column.width(28))
        .column("Total", column -> column.format(CurrencyExcelFormats.USD))
        .formulaColumn("VAT", column -> column
            .round("Total", 2)
            .format(CurrencyExcelFormats.USD))
        .formulaColumn("Grand Total", column -> column
            .SUM("Total", "VAT")
            .format(CurrencyExcelFormats.USD)))
    .build();

SqlReportDefinition definition = SqlReportDefinition.builder()
    .code("invoice-workbook")
    .sheet(invoices)
    .maxRows(500_000)
    .queryTimeoutSeconds(120)
    .fetchSize(1000)
    .build();
application.yml
report-boot:
  sql:
    enabled: true
    file-name-suffix: .xlsx
    expiry-minutes: 30
    tenant:
      column: tenant_id
      parameter-name: tenantId

Dynamic Excel Library

Treat Excel as code while addressing source and calculated data by business column name.

Dynamic Excel is the most capable spreadsheet provider, but it remains one module in the wider platform. It is template-free: builders define sheets, columns, formula columns, styles, summaries, charts, KPI cards, filters and connected slices.

pom.xml
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-excel</artifactId>
  <version>0.1.0-MVP</version>
</dependency>
CapabilityDeveloper experienceUse when
Business-name column referencesSUM("Total", "VAT") instead of A1 mathColumns can move or be calculated
272 fluent Excel functionscol.SUM(...), col.IF(...), col.VLOOKUP(...)The developer should discover inputs through Java methods
Named formats and colorsCurrencyExcelFormats.USD, DateExcelFormats.ISO_DATE, ExcelColors.*Avoid magic number-format and hex strings
Column groupsMerged parent headers over two or more columnsA business concept spans child columns
Group/sort + summariesRepeated tables with per-group and grand totalsOne query produces department/customer sections
Section cellsMerged title, text, parameter or formula above dataA sheet needs report context before the table
9 chart contractsColumn, bar, line, area, pie, doughnut, scatter, radar, comboGenerate a dashboard sheet from data columns
Connected slicesDropdown filters drive KPI/formula/chart rangesWorkbook consumers need interactive what-if views
Streaming + metadataLarge XLSX output and optional _Report Info sheetGoverned high-volume exports
Invoice workbook
SqlReportSheet invoices = SqlReportSheet.builder()
    .sheetName("Invoices")
    .sqlFile("invoice-report.sql")
    .sortBy("Created On", "Invoice No")
    .excel(excel -> excel
        .header(style -> style
            .backgroundColor(ExcelColors.Section.HEADER_BACKGROUND)
            .fontColor(ExcelColors.Section.HEADER_TEXT)
            .bold(true))
        .column("Customer", column -> column.width(28))
        .column("Total", column -> column.format(CurrencyExcelFormats.USD))
        .formulaColumn("VAT", column -> column
            .round("Total", 2)
            .format(CurrencyExcelFormats.USD))
        .formulaColumn("Grand Total", column -> column
            .SUM("Total", "VAT")
            .format(CurrencyExcelFormats.USD)))
    .build();

SqlReportDefinition definition = SqlReportDefinition.builder()
    .code("invoice-workbook")
    .sheet(invoices)
    .maxRows(500_000)
    .queryTimeoutSeconds(120)
    .fetchSize(1000)
    .build();

A calculated column becomes a normal named column for later formulas, summaries, charts and filters. That is the central simplification: developers reason in business names, and the renderer resolves physical Excel references after the final layout is known.

CSV Library

Reuse the tabular report definition for portable delimited output.

Use CSV for machine-readable extracts, integrations and data movement. A one-sheet definition becomes one CSV; a multi-sheet definition becomes a ZIP with one CSV per sheet.

pom.xml
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-csv</artifactId>
  <version>0.1.0-MVP</version>
</dependency>
application.yml
report-boot:
  csv:
    enabled: true
    delimiter: ","
    include-header: true
    charset: UTF-8
Generate CSV
GeneratedReport report = reportService.generate(
    "invoice-summary",
    definition,
    parameters,
    ReportOutput.CSV
);
ChoiceMeaning
ExcelHuman-facing layout, formulas, styles and dashboard interactions
CSVPortable flat data; ignores workbook-only presentation
JXLSA predesigned spreadsheet template is the source of layout

Custom Governance

Govern existing PDF, Excel, CSV, HTML, or Word exports without rewriting the renderer. Developers pass bytes plus a config class; Report-Boot secures, stores, downloads, emails, and prepares the artifact for Insights.

Use this path when the report already exists. The application may render the file with Apache POI, EasyExcel, JasperReports, JXLS, BIRT, Thymeleaf, OpenHTMLToPDF, a vendor SDK, or internal code. Report-Boot does not render those bytes in custom governance; it governs the finished artifact.

Report-Boot capability tree showing reporting, governance, monitoring, design and dashboards milestones
Transparent SVG architecture tree for the first Spring Boot milestone. It is layered so the website can animate or parallax the branches later.

How it flows

1Existing renderer produces byte[]
2Developer calls customReportExportService.exportBytes
3Report-Boot validates the config class
4Report-Boot creates a report order UUID
5Report-Boot stores content and checksum
6Download, email, secure link and Insights metadata use the same lifecycle
Developer passesExamplePurpose
Config classExistingFinanceExportConfig.classStable report code, output, security and metadata
Bytesbyte[] bytesAlready-rendered file from the developer's current library
Output typeReportOutput.EXCELDeclares PDF, Excel, CSV, HTML or Word
File namefinance.xlsxOptional override for the downloaded file name
Content typeapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetOptional override when the default MIME type is not enough
ExistingFinanceExportConfig.java
@ReportTemplate(
    code = "existing-finance-export",
    title = "Existing Finance Export",
    templateFile = "existing-finance-export",
    output = ReportOutput.EXCEL
)
@ReportEngineType(ReportEngine.CUSTOM)
@ReportFileName("finance.xlsx")
@ReportSecured(expiryMinutes = 30, oneTimeDownload = true)
@ReportDescription("Existing export governed by Report-Boot.")
public class ExistingFinanceExportConfig {
}
Existing bytes to governed report
byte[] bytes = existingFinanceExporter.export(request);

GeneratedReport report = customReportExportService.exportBytes(
        ExistingFinanceExportConfig.class,
        bytes,
        ReportOutput.EXCEL,
        "finance.xlsx",
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
ReportOutputExtensionDefault content type
PDF.pdfapplication/pdf
EXCEL.xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
CSV.csvtext/csv
HTML.htmltext/html
WORD.docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.document

PDF byte rendering stays in the developer's existing renderer. For example, JasperReports, OpenHTMLToPDF, PDFBox, iText, BIRT, or a vendor service can produce the byte array. Report-Boot receives those bytes and governs the result.

Existing PDF bytes
byte[] pdf = existingPdfRenderer.render(request);

GeneratedReport report = customReportExportService.exportBytes(
        ExistingFinancePdfConfig.class,
        pdf,
        ReportOutput.PDF,
        "finance.pdf",
        "application/pdf");

After generation, controllers should download through ReportService and use the starter response helper. Attachment means the browser downloads the file. Inline means the browser may preview it in the tab, usually for PDF or HTML.

Download endpoint
@GetMapping("/reports/{uuid}/download")
ResponseEntity<StreamingResponseBody> download(
        @PathVariable UUID uuid,
        @RequestParam(name = "token", required = false) String token) {

    GeneratedReport report = token == null || token.isBlank()
            ? reportService.download(uuid)
            : reportService.download(uuid, token);

    return ReportDownloadResponseBuilder.attachment(report);
}
MethodBrowser behaviorRecommended for
ReportDownloadResponseBuilder.attachment(report)Download/save fileExcel, CSV, Word, sensitive PDF and most business reports
ReportDownloadResponseBuilder.inline(report)Preview in browser when supportedIntentional PDF or HTML preview

For email, attach the governed GeneratedReport or send a secure link. Secure links are better for sensitive reports because expiry, tokens, one-time download, checksum and download audit stay inside Report-Boot.

Secure email link
String downloadUrl = UriComponentsBuilder
        .fromHttpUrl("https://app.example.com/reports/" + report.getReportOrderUuid() + "/download")
        .queryParam("token", report.getAccessToken())
        .toUriString();

reportEmailSender.send(ReportEmail.builder()
        .to("finance@example.com")
        .subject("Secure finance report")
        .html("<p>Download your report: <a href=\"" + downloadUrl + "\">Open secure link</a></p>")
        .metadata("deliveryMode", "secure-link")
        .metadata("reportOrderUuid", report.getReportOrderUuid())
        .build());
Report-Boot handlesWhy teams use it
Report order UUIDOne durable identity for download, email, audit, support and Insights
Storage and checksumConsistent artifact storage and tamper detection
Access token and expiryTime-limited secure links for existing reports
One-time downloadOptional single-use access for sensitive reports
Email deliveryAttachment or secure-link delivery without custom plumbing
Insights metadataExisting reports become visible to the incoming Insights platform

Programmable Reports

Build rich workbooks and portable extracts from trusted SQL without maintaining a template.

FileHomeInsertDrawPage LayoutFormulasDataReviewViewAutomateHelp
B6fx=SUM('Sliced Dashboard Data'!E:E)
Dashboard
Payment Status
Selected
All
Paid
Unpaid
Customer
Selected
All
Acme Corp
Beta LLC
Cedar Group
Day
Selected
All
Day 1
Day 5
Day 8
Sliced Revenue
$4,375.75
Sliced Invoices
3
Sliced Average
$1,458.58
Revenue Trend
Day 1Day 5Day 8
Invoices by Day
Day 1
Day 5
Day 8
Revenue with Change
Day 1
Day 5
Day 8
RevenueRevenue Change %

Sliced Excel dashboard output pattern

One generated workbook can contain source data, interactive dashboard-style sheets, slicer-like filters, charts, KPIs, and a metadata dictionary from the same trusted SQL definition.

How it flows

1Trusted SQL + named parameters
2SqlReportDefinition
3Tabular data
4Excel or CSV renderer
5GeneratedReport
6Download/govern

The SQL module defines what data exists. The Excel module defines how that data behaves in a workbook. They meet through provider-neutral tabular contracts and the same ReportService lifecycle used by annotation reports.

InvoiceDefinition.java
SqlReportSheet invoices = SqlReportSheet.builder()
    .sheetName("Invoices")
    .sqlFile("invoice-report.sql")
    .sortBy("Created On", "Invoice No")
    .excel(excel -> excel
        .header(style -> style
            .backgroundColor(ExcelColors.Section.HEADER_BACKGROUND)
            .fontColor(ExcelColors.Section.HEADER_TEXT)
            .bold(true))
        .column("Customer", column -> column.width(28))
        .column("Total", column -> column.format(CurrencyExcelFormats.USD))
        .formulaColumn("VAT", column -> column
            .round("Total", 2)
            .format(CurrencyExcelFormats.USD))
        .formulaColumn("Grand Total", column -> column
            .SUM("Total", "VAT")
            .format(CurrencyExcelFormats.USD)))
    .build();

SqlReportDefinition definition = SqlReportDefinition.builder()
    .code("invoice-workbook")
    .sheet(invoices)
    .maxRows(500_000)
    .queryTimeoutSeconds(120)
    .fetchSize(1000)
    .build();
InvoiceController.java
@GetMapping("/download")
ResponseEntity<byte[]> download(
        @RequestParam LocalDate fromDate,
        @RequestParam LocalDate toDate,
        @RequestParam String tenantId,
        @RequestParam(defaultValue = "EXCEL") ReportOutput output) {
    GeneratedReport report = reportService.generate(
        "invoice-workbook",
        invoiceDefinitions.invoiceSummary(),
        Map.of("fromDate", fromDate, "toDate", toDate, "tenantId", tenantId),
        output
    );
    return downloadResponse(report);
}

Business Column Names

The strongest usability feature: developers work with report headers, including calculated columns.

Alias SQL columns with the names the business sees. Every style, formula, group, chart, filter, KPI, summary, and slice then references those names. No A1 coordinates, no manual row arithmetic, and no coupling to database column names.

Column-first design
select customer_name as "Customer",
       total as "Total"
from invoices

.column("Total", c -> c.format(CurrencyExcelFormats.USD))
.formulaColumn("VAT", c -> c.round("Total", 2))
.formulaColumn("Grand Total", c -> c.SUM("Total", "VAT"))
.summaryFooter(f -> f.formula("Grand Total", c -> c.SUM("Grand Total")))
.addChart(DynamicExcelColumnChart.of(c -> c
    .categoryColumn("Customer")
    .valueColumn("Grand Total")))
  • Calculated columns become first-class names: Grand Total can be summarized, styled, or referenced by later formulas.
  • Column groups merge visual headers while formulas keep using stable names.
  • Conditional formatting overrides the base column background only when its rule matches.
  • Renaming a SQL alias produces a clear configuration mismatch instead of silently pointing to the wrong cell.

Builder Method Dictionary

A compact map of the report, sheet, and Excel builder surface.

MethodWhat it gives the developer
SqlReportDefinition.codeStable report identity used by generation and governance.
sheet / sheetsAdds one or more independently queried workbook sheets.
maxRowsHard row guardrail per sheet; default 500,000.
queryTimeoutSecondsJDBC query timeout; default 120 seconds.
fetchSizeJDBC streaming hint; default 1,000.
defaultParametersTrusted defaults merged before request parameters.
dashboardWorkbook-level dashboard sheet and layout options.
sheetNameHuman-readable Excel sheet name.
sql / sqlFileTrusted inline query or classpath SQL under report-boot/sql.
parametersDefaults scoped to one sheet.
groupByCreates repeated table sections using one or more column names.
sortByOrders rows predictably before grouping and rendering.
betweenGroupSpaceRowsSpacing between groups; grouping defaults to three rows.
excelConfigures the sheet using business column names.
addChartAdds a typed chart contract to the generated dashboard.
addKpiAdds a calculated dashboard KPI card.
addFilterAdds an Excel-native filter linked to dashboard calculations.
addSliceAdds a connected dropdown slice panel.
headerStyles the repeated table header.
columnStyles a source column by its SQL alias/header.
columnBackgroundSets a base color that specific styles and conditions may override.
columnGroupCreates a merged parent header above related columns.
formulaColumnAdds a calculated column by name; formulas can reference source or calculated columns.
summaryFooterAdds per-group summaries and an all-groups summary.
conditionalFormatApplies data-driven styles after base column styling.
sectionCellPlaces merged titles, parameter values, text, or formulas above the table.
includeColumnLimits output to an explicit column allowlist.

Formula DSL

Use code completion and column names instead of hand-writing Excel expressions.

Formula examples
.formulaColumn("VAT", column -> column
    .round("Total", 2)
    .format(CurrencyExcelFormats.USD))

.formulaColumn("Grand Total", column -> column
    .SUM("Total", "VAT", "Shipping"))

.formulaColumn("Invoice Label", column -> column
    .concatenate("Customer", "Invoice No")) // default: " - "

.formulaColumn("Compact Label", column -> column
    .concatenate("Customer", "Invoice No")
    .symbol(" / "))

.formulaColumn("Payment Flag", column -> column
    .IF("Paid", "Paid", "Outstanding"))

SUM and similar functions accept varargs, so developers can pass any number of column names. concatenate assumes its String arguments are columns and inserts the default separator automatically. Raw formula(String) remains available for legacy formulas.

Friendly helperUse
SUM / sumAdd one or many columns or values.
AVERAGE / averageMean of columns or values.
MIN, MAX, COUNT, COUNTACommon aggregation without expression strings.
round, roundUp, roundDownValue plus digits.
IF / ifElse, IFERROR, IFNAConditional and fallback expressions.
concatenate / joinJoin named columns with a default or custom symbol.
ref, text, number, boolExplicit operands for advanced formulas.
functionEscape hatch by name or ExcelFunction enum.
UPPERCASE methodsOne discoverable method for every catalog entry below.

Formula Function Catalog

272 uppercase methods generated from Apache POI's built-in Excel function metadata.

Call them directly, for example column.SUM(...), column.VLOOKUP(...), or column.NPV(...). Object... preserves Excel functions with variable or mixed argument shapes. This catalog reflects the current POI-backed implementation; newer Microsoft 365-only functions are not implied unless added to the library.

Available methods (272)
ABS, ABSREF, ACOS, ACOSH, ADDRESS, AND, APP_TITLE, AREAS, ARGUMENT, ASC,
ASIN, ASINH, ATAN, ATAN2, ATANH, AVEDEV, AVERAGE, AVERAGEA, BETADIST, BETAINV,
BINOMDIST, CALL, CEILING, CELL, CHAR, CHIDIST, CHIINV, CHITEST, CHOOSE, CLEAN,
CODE, COLUMN, COLUMNS, COMBIN, CONCATENATE, CONFIDENCE, CORREL, COS, COSH, COUNT,
COUNTA, COUNTBLANK, COUNTIF, COVAR, CRITBINOM, DATE, DATEDIF, DATESTRING, DATEVALUE,
DAVERAGE, DAY, DAYS360, DB, DBCS, DCOUNT, DCOUNTA, DDB, DEGREES, DEVSQ, DGET,
DMAX, DMIN, DOLLAR, DPRODUCT, DSTDEV, DSTDEVP, DSUM, DVAR, DVARP, ENABLE_TOOL,
END_IF, ERROR, ERROR_TYPE, EVALUATE, EVEN, EXACT, EXEC, EXP, EXPONDIST, FACT,
FALSE, FDIST, FIND, FINDB, FINV, FISHER, FISHERINV, FIXED, FLOOR, FORECAST,
FREQUENCY, FTEST, FV, GAMMADIST, GAMMAINV, GAMMALN, GEOMEAN, GET_CELL, GET_DOCUMENT,
GET_WINDOW, GET_WORKBOOK, GET_WORKSPACE, GETPIVOTDATA, GOTO, GROWTH, HARMEAN,
HLOOKUP, HOUR, HYPERLINK, HYPGEOMDIST, IF, INDEX, INDIRECT, INFO, INT, INTERCEPT,
IPMT, IRR, ISBLANK, ISERR, ISERROR, ISLOGICAL, ISNA, ISNONTEXT, ISNUMBER, ISPMT,
ISREF, ISTEXT, JIS, KURT, LARGE, LAST_ERROR, LEFT, LEFTB, LEN, LENB, LINEST, LN,
LOG, LOG10, LOGEST, LOGINV, LOGNORMDIST, LOOKUP, LOWER, MATCH, MAX, MAXA, MDETERM,
MEDIAN, MID, MIDB, MIN, MINA, MINUTE, MINVERSE, MIRR, MMULT, MOD, MODE, MONTH,
N, NA, NEGBINOMDIST, NORMDIST, NORMINV, NORMSDIST, NORMSINV, NOT, NOW, NPER,
NPV, NUMBERSTRING, ODD, OFFSET, OR, PEARSON, PERCENTILE, PERCENTRANK, PERMUT,
PHONETIC, PI, PMT, POISSON, POWER, PPMT, PRESS_TOOL, PROB, PRODUCT, PROPER, PV,
QUARTILE, RADIANS, RAND, RANK, RATE, REGISTER_ID, RELREF, REPLACE, REPLACEB, REPT,
RETURN, RIGHT, RIGHTB, ROMAN, ROUND, ROUNDDOWN, ROUNDUP, ROW, ROWS, RSQ,
SAVE_TOOLBAR, SEARCH, SEARCHB, SECOND, SIGN, SIN, SINH, SKEW, SLN, SLOPE, SMALL,
SQRT, STANDARDIZE, STDEV, STDEVA, STDEVP, STDEVPA, STEP, STEYX, SUBSTITUTE,
SUBTOTAL, SUM, SUMIF, SUMPRODUCT, SUMSQ, SUMX2MY2, SUMX2PY2, SUMXMY2, SYD, T,
TAN, TANH, TDIST, TEXT, TIME, TIMEVALUE, TINV, TODAY, TRANSPOSE, TREND, TRIM,
TRIMMEAN, TRUE, TRUNC, TTEST, TYPE, UPPER, USDOLLAR, VALUE, VAR, VARA, VARP,
VARPA, VDB, VLOOKUP, WEEKDAY, WEIBULL, WINDOW_TITLE, YEAR, YEN, ZTEST

Formats, Colors, and Styles

Discover named choices through code completion instead of memorizing format strings and hex values.

ClassConstants
CurrencyExcelFormatsUSD, EUR, GBP, JPY, AUD
DateExcelFormatsDATE_ISO, DATE_SHORT, DATE_LONG, DATE_TIME_ISO, DATE_TIME_WITH_SECONDS, MONTH_NAME, YEAR_MONTH, WEEKDAY_SHORT
NumberExcelFormatsGENERAL, INTEGER, DECIMAL_2, DECIMAL_4, PLAIN_INTEGER, SCIENTIFIC, FRACTION
PercentExcelFormatsPERCENT, PERCENT_2, PERCENT_4
TextExcelFormatsTEXT, PHONE_E164, POSTAL_CODE_US, POSTAL_CODE_CANADA
ExcelColors.PaletteBLACK, WHITE, GRAY_50/100/200/400/700, BRAND_BLUE, BRAND_BLUE_DARK
ExcelColors.StatusSUCCESS_BG/TEXT, ERROR_BG/TEXT, WARNING_BG/TEXT, INFO_BG/TEXT
ExcelColors.SectionHEADER_BACKGROUND/TEXT, SUBTITLE_BACKGROUND/TEXT
Style precedence
.columnBackground("Status", ExcelColors.Palette.GRAY_50)
.column("Status", c -> c.bold(true))
.conditionalFormat("Status", rule -> rule
    .equalTo("Failed")
    .style(s -> s
        .backgroundColor(ExcelColors.Status.ERROR_BG)
        .fontColor(ExcelColors.Status.ERROR_TEXT)))

The base column background is applied first. Explicit column style and matching conditional rules may override it, which makes a sensible default coexist with exception highlighting.

Groups, Summaries, and Sections

Create repeatable report sections in one sheet, with isolated totals and a final grand total.

Department slices
SqlReportSheet.builder()
    .sheetName("Department Report")
    .sqlFile("department-report.sql")
    .groupBy("Department", "Market")
    .sortBy("Department", "Market", "Employee")
    .betweenGroupSpaceRows(3)
    .excel(excel -> excel
        .columnGroup("Employee", "Department", "Market", "Employee")
        .columnGroup("Money", "Gross", "VAT", "Net")
        .summaryFooter(footer -> footer
            .label("Slice Total")
            .labelColumn("Employee")
            .formula("Gross", f -> f.SUM("Gross"))
            .formula("VAT", f -> f.SUM("VAT"))
            .formula("Net", f -> f.SUM("Net"))))
    .build();
  • Rows are sorted before the group key is evaluated.
  • Each group repeats merged parent headers and normal column headers.
  • Each group summary references only that group's row range.
  • After the final group, Report-Boot writes an all-groups total summary.
  • If spacing is omitted, grouped output uses three blank rows.
Section cells
.sectionCell(new DynamicExcelSectionCell(
    1, 1,
    DynamicExcelSectionCellType.TEXT,
    "Monthly Revenue Report",
    DynamicExcelCellStyle.of(s -> s.bold(true).fontSize(16)),
    5, 1
))

A section cell is content placed before the generated table. Use it for report titles, parameter values, prepared labels, or formulas. Its row, column, merge width/height, value type, and style are explicit while the table starts below the reserved section.

Dashboards, Charts, and Slices

Declare analytical intent by column name; Report-Boot owns workbook drawing and placement.

How it flows

1SQL aliases define model
2Add chart/KPI/filter/slice contracts
3Generate source sheet
4Build hidden calculation model
5Build Dashboard sheet
6Open interactive workbook
Chart contractBest use
DynamicExcelLineChartTime and ordered-category trends.
DynamicExcelColumnChartCategory comparison.
DynamicExcelColumnPercentageChangeChartValues with a percentage movement overlay.
DynamicExcelBarChartRankings and long category labels.
DynamicExcelAreaChartVolume and accumulated trend emphasis.
DynamicExcelPieChartSmall part-to-whole comparisons.
DynamicExcelDoughnutChartPart-to-whole with center space.
DynamicExcelScatterChartNumeric X/Y relationships; categoryColumn must be numeric.
DynamicExcelRadarChartProfiles and pattern comparison.
Dashboard contracts
.addKpi(DynamicExcelKpiCard.of(kpi -> kpi
    .title("Sliced Revenue")
    .valueColumn("Revenue")
    .aggregation(DynamicExcelAggregationType.SUM)))
.addSlice(DynamicExcelDropdownSlice.of(slice -> slice
    .title("Payment Status")
    .column("Payment Status")))
.addChart(DynamicExcelLineChart.of(chart -> chart
    .title("Revenue Trend")
    .categoryColumn("Day Label")
    .valueColumn("Revenue")))

The developer does not calculate chart anchors or build Apache POI drawing objects. Charts are placed in declaration order on a standard two-column dashboard grid. Connected slices drive the hidden model, KPIs, and charts from familiar business headers.

Streaming, Metadata, and CSV

Production controls stay outside business definitions and can be tuned centrally.

SettingDefaultMeaning
max-rows-per-sheet1,048,576Excel row boundary/guardrail.
overflow-policySPLIT_SHEETSContinue in numbered sheets when needed.
window-size1,000SXSSF rows retained in memory.
compress-temp-filestrueTrades CPU for smaller temporary files.
auto-size-columnsfalseWidth estimation is opt-in for predictable large-export cost.
freeze-header / auto-filtertrue / trueUsable generated tables by default.
include-metadata-sheetfalseAdds report identity, parameters, and data dictionary.

The same SqlReportDefinition can request ReportOutput.CSV. A single sheet becomes CSV; multiple sheets are packaged as a ZIP. CSV intentionally ignores Excel-only styles, formulas, charts, and dashboard controls.

Delivery & Observability

Delivery & Observability

Review these topics in order, or jump directly to the card you need.

Email Library

Deliver any supported report manually or on a governed schedule, as an attachment or secure link.

The email module is provider-neutral. It can generate from an annotation DTO, generate a SQL/builder report, or attach an already generated report. Email templates live under report-boot/email-templates so presentation stays outside Java strings.

pom.xml
<dependency>
  <groupId>com.reportboot</groupId>
  <artifactId>report-boot-email</artifactId>
  <version>0.1.0-MVP</version>
</dependency>
FeatureWhenGovernance/safety
Manual attachmentA request or domain service decides nowIdempotency key prevents accidental retries
SQL/builder attachmentReport has no annotation DTOSame delivery service accepts definitions and parameters
Secure linkAttachment is large or sensitiveSigned token + rb_report_order expiry + optional one-time claim
@ReportEmailJobCron-driven recurring deliveryJob synchronized to rb_email_job and checked before each run
@ReportEmailConditionSend only when report/domain data qualifiesSkipped outcomes remain visible
Distributed idempotencyMultiple application instances may fireDatabase claim prevents duplicate sends
rb_email_run / rb_email_logOperations and troubleshootingEvery run and terminal outcome has rich context
application.yml
spring:
  mail:
    host: ${REPORT_BOOT_SMTP_HOST}
    port: ${REPORT_BOOT_SMTP_PORT:587}
    username: ${REPORT_BOOT_SMTP_USERNAME}
    password: ${REPORT_BOOT_SMTP_PASSWORD}
report-boot:
  email:
    enabled: true
    from: ${REPORT_BOOT_EMAIL_FROM}
    templates-path: classpath:/report-boot/email-templates

Email Delivery

Send any generated provider output as an attachment or send a short-lived secure link.

How it flows

1Build ReportEmail
2Reserve idempotency key
3Render report if attached
4Render HTML email template
5Send through Spring Mail
6Persist run + rich log
Email builder
ReportEmail email = ReportEmail.builder()
    .jobKey("month-end-invoice")
    .idempotencyKey("invoice-2026-07-final")
    .to("finance@example.com")
    .subject("Invoice report")
    .template("invoice-report-ready")
    .data("invoiceNumber", "INV-1001")
    .metadata("username", currentUser)
    .metadata("tenantId", tenantId)
    .attachReport(invoiceDto)
    .build();

ReportEmailResult result = reportEmailSender.send(email);
  • Templates live under report-boot/email-templates and use {{name}} placeholders.
  • The sender is governed by configuration, not arbitrary request values.
  • A duplicate is returned as SKIPPED and remains visible in email governance logs.
  • Use a stable business idempotency key for scheduled/event flows; omit it in ad hoc testing only when repeats are intended.

Scheduled Email Jobs

A Spring bean registers itself, syncs to the database, and executes only while the job is active.

How it flows

1Spring discovers bean
2Sync rb_email_job
3Schedule cron
4Read active database state
5Evaluate conditions
6Build and send
7Persist rb_email_run and rb_email_log
DailyInvoiceEmailJob.java
@Component
@ReportEmailJob(
    key = "daily-invoice-email",
    name = "Daily Invoice Email",
    cron = "0 0 8 * * *",
    subject = "Daily invoice report",
    template = "daily-invoice-email"
)
@ReportEmailCondition(
    field = "totalAmount",
    operator = ReportEmailConditionOperator.GREATER_THAN,
    value = "0"
)
class DailyInvoiceEmailJob implements ReportEmailJobProvider {
    public ReportEmail buildEmail() {
        return ReportEmail.builder()
            .to(recipient)
            .template("daily-invoice-email")
            .attachReport(sampleReport())
            .build();
    }
}

The database row is the operational switch. Developers keep the declarative cron and build logic in code; operators can disable a job without redeploying. JDBC idempotency prevents duplicate sends across service instances.

Database and Governance

Framework tables are predictable, prefixed, schema-aware, and safe to initialize on startup.

Default tableOwnerPurpose
rb_report_orderStarterDurable UUID, expiry, status, storage reference, token hash, and download state.
rb_logStarterCentral report generation/download governance across engines.
rb_email_jobEmailRegistered cron definition and active switch.
rb_email_idempotencyEmailDistributed duplicate-send reservation and expiry.
rb_email_runEmailOne scheduled/manual trigger execution.
rb_email_logEmailRich delivery result, recipients, report, template, identity, errors, and metadata.
rb_insight_*InsightsOperational catalog, orders, failures, and analytics using the module-owned insight segment.
Database settings
report-boot:
  database:
    initialize-schema: true
    schema: reporting
    table-prefix: rb_

Startup initialization uses create schema/table/index if not exists and does not drop or alter data. Disable initialize-schema and reproduce the definitions in Flyway or Liquibase when your organization requires migration ownership.

Insights API Library

Stable observability contracts without forcing a storage technology.

Add the API module when a service, control center or custom sink must exchange Report-Boot telemetry. It contains DTOs and interfaces only; it does not install a Logback appender or database implementation.

ContractPurpose
ReportBootInsightEventStructured lifecycle event exchanged with insight consumers
ReportBootInsightEventWriterApplication/provider boundary for emitting structured events
ReportBootLogEntrySerializable library-log record with level, logger, correlation and exception data
ReportBootLogSinkPersistence/forwarding port implemented by the consuming application
Dashboard and audit DTOsStable read models for control-center integrations
Custom sink
@Component
class JpaReportBootLogSink implements ReportBootLogSink {
    private final LibraryLogEntryRepository repository;

    @Override
    public void persist(ReportBootLogEntry entry) {
        repository.save(ReportBootLogEntity.from(entry));
    }
}

Insights Spring Boot Starter

Automatically capture Report-Boot library logs and forward them to your sink.

The starter registers ReportBootLibraryLogbackAppender, captures the com.reportboot hierarchy or REPORT_BOOT_LIBRARY marker, buffers events in a ring buffer and calls the available ReportBootLogSink.

application.yml
report-boot:
  insights:
    enabled: true
    mode: db_only
    logs:
      enabled: true
      logger-prefix: com.reportboot
      marker: REPORT_BOOT_LIBRARY
      ring-buffer-size: 1000
SettingWhen/why
enabledMaster switch for the runtime capture integration
logs.enabledDisable only log capture while retaining other future insight behavior
logger-prefixNarrow capture to Report-Boot or an application-specific hierarchy
markerInclude explicitly marked records outside the normal prefix
ring-buffer-sizeBalance recent live-stream history against application memory
modeReserved for future routing; current forwarding still depends on the sink

For a full operational view, pair this starter with the API contracts, a persistence sink, the control-center SSE endpoints and the Insights web application. Correlation ID, report code/name, engine, output, user and exception details should be populated at centralized boundaries.

Insights and Log Streaming

Inspect reports by correlation ID, report code, engine, output, instance, user, tenant, status, and failure.

How it flows

1Libraries log with marker
2Starter captures events
3Persist/stream
4Control Center exposes APIs
5Insights filters table or follows console
  • rb_log is the centralized audit source for extraction operations.
  • rb_email_log adds email-specific delivery detail.
  • SSE clients must send Accept: text/event-stream and keep the connection open.
  • The console appends from top to bottom; the newest log appears at the bottom like a real terminal.
  • Use correlationId to connect an API request, report generation, renderer, storage, download, and email result.

Design & AI

Design & AI

Review these topics in order, or jump directly to the card you need.

Designer Library

A trusted JSON contract that turns visual report intent into an executable SQL definition.

The Designer library is a backend contract/mapping layer, not the canvas itself. A frontend posts DesignerSqlExcelRequest; the definition service validates it, resolves trusted dataSourceRef values, and builds SqlReportDefinition for normal SQL + Excel execution.

How it flows

1Visual editor
2DesignerSqlExcelRequest JSON
3Validate shape
4Resolve dataSourceRef
5Build SqlReportDefinition
6Generate with ReportService
ContractWhat the developer controls
DesignerSqlExcelRequestReport code, parameters, sheets and execution limits
DesignerSqlExcelSheetTrusted source reference, visible columns, formulas and sheet options
DesignerFormulaColumnCalculated business column
DesignerConditionalFormatData-driven style rules
DesignerSummaryFooterSheet/group aggregate definitions
DesignerSqlExcelDataSourceRegistryServer-owned mapping from safe key to trusted SQL
DesignerSqlExcelDefinitionServiceValidation and conversion into executable builders
Controller
@PostMapping("/api/reports/designer/sql-excel/download")
ResponseEntity<byte[]> download(@RequestBody DesignerSqlExcelRequest request) {
    SqlReportDefinition definition = designerDefinitionService.buildDefinition(request);
    GeneratedReport report = reportService.generate(
        request.reportCode(), definition, request.parameters(), ReportOutput.EXCEL);
    return downloadResponse(report);
}

Never accept arbitrary SQL from an untrusted browser. Prefer dataSourceRef so the server owns query text, tenant restrictions and allowed parameters.

Designer JSON

Convert a governed visual definition into the same trusted SQL/Excel runtime.

How it flows

1Designer creates JSON
2Backend validates dataSourceRef
3Build SqlReportDefinition
4Execute trusted SQL
5Render Excel
6Download workbook

The designer request can describe sheets, columns, formulas, styles, conditional rules, groups, and summaries. It references a trusted server-side data source; it must not become an endpoint for arbitrary untrusted SQL.

Controller
@PostMapping(value = "/download", consumes = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<byte[]> download(@RequestBody DesignerSqlExcelRequest request) {
    SqlReportDefinition definition = definitions.buildDefinition(request);
    GeneratedReport report = reportService.generate(
        definitions.reportCode(request), definition, request.parameters(), ReportOutput.EXCEL);
    return downloadResponse(report);
}

AI Library

A secured server-side Gemini bridge that assists design without exposing provider secrets.

Report-Boot AI proposes or explains Designer JSON; it does not render report files. Design mode returns a currentRequest-compatible definition, while chat mode returns an answer and rejects design-shaped output.

How it flows

1Designer prompt
2Report-Boot backend proxy
3Validate token and limits
4Gemini
5Design JSON or chat
6Developer reviews
7Normal Designer execution
application.yml
report-boot:
  ai:
    enabled: true
    max-prompt-characters: 4000
    gemini:
      api-key: ${REPORT_BOOT_AI_GEMINI_API_KEY}
      default-model: gemini-flash-latest
      allowed-models: [gemini-flash-latest, gemini-2.5-flash]
      request-timeout: 45s
      temperature: 0.2
    designer-proxy:
      enabled: true
      require-proxy-token: true
      token-header: X-Report-Boot-AI-Token
      proxy-token: ${REPORT_BOOT_AI_PROXY_TOKEN}
GuardrailWhy
Provider API key stays on serverBrowser users cannot extract the Gemini credential
Proxy token required in productionOnly approved clients can spend provider quota
Allowed model listControls cost and contract compatibility
Prompt length + timeoutBounds abuse and stalled requests
Human review before executionAI output is a proposed definition, not trusted SQL

AI-Assisted Design

Keep provider credentials server-side and constrain models, prompts, and proxy access.

application.yml
report-boot:
  ai:
    enabled: false
    max-prompt-characters: 4000
    gemini:
      api-key: ${REPORT_BOOT_AI_GEMINI_API_KEY}
      default-model: gemini-flash-latest
      allowed-models: [gemini-flash-latest, gemini-2.5-flash]
      request-timeout: 45s
      temperature: 0.2
    designer-proxy:
      enabled: true
      path: /api/report-boot/ai/designer/generate
      require-proxy-token: true
      token-header: X-Report-Boot-AI-Token
      proxy-token: ${REPORT_BOOT_AI_PROXY_TOKEN}

AI proposes a designer contract; backend validation and trusted data-source rules remain authoritative. Never expose the Gemini key in the browser.

Demo & API Testing

Demo & API Testing

Review these topics in order, or jump directly to the card you need.

Demo Application

The executable reference for APIs, templates, SQL, SMTP, secure links, governance and Postman.

Do not add report-boot-demo as a production dependency. Run it locally to see how every public library is composed, inspect controllers and definitions, and exercise the same requests from the supplied Postman collection.

Run from repository root
./mvnw spring-boot:run -pl library/report-boot-demo -am
Demo areaWhat it provesStart with
Jasper/JXLS/BIRT/ThymeleafAnnotation DTO + template provider lifecyclePOST /api/reports/{provider}/invoice/download
SQL + Excel/CSVDefinition-first multi-output reportingGET /api/reports/sql/invoices/download
Formula catalogFluent function surface and named calculated columnsGET /api/reports/sql/invoices/formulas/all/download
Grouped workbooksortBy, groupBy, repeated headers and summariesGET /api/reports/sql/invoices/group-sort/download
Excel dashboardsCharts, filters, slices and metadataDashboard cookbook endpoints
DesignerJSON to trusted SQL definitionPOST /api/reports/designer/sql-excel/download
EmailAttachments and five-minute secure linkPOST /api/reports/email/thymeleaf/invoice
Governancerb_log, rb_report_order and email tablesInspect PostgreSQL after requests

Run the Demo

Start the reference application, then use the cookbooks exactly as shown.

How it flows

1Start PostgreSQL
2Set environment
3Run Spring Boot demo
4Call localhost:8080 API
5Inspect file/tables/logs
PowerShell
$env:REPORT_BOOT_DATASOURCE_URL="jdbc:postgresql://localhost:5432/report_boot_control_center"
$env:REPORT_BOOT_DATASOURCE_USERNAME="report_boot"
$env:REPORT_BOOT_DATASOURCE_PASSWORD="report_boot"
mvn -pl library/report-boot-demo -am spring-boot:run

The demo registers all provider modules, SQL/Excel, CSV, Designer, AI, Email, PostgreSQL, filesystem storage, JDBC orders, and governance. It listens on port 8080.

Postman and Demo APIs

Import one collection, set environment variables, and test every library against the demo.

How it flows

1Run demo
2Import collection JSON
3Create environment
4Send generation request
5Capture reportOrderUuid
6Download or inspect output
Start demo
./mvnw spring-boot:run -pl library/report-boot-demo -am
Import this file in Postman
docs/postman/report-boot-demo.postman_collection.json
VariableInitial valueUsed by
baseUrlhttp://localhost:8080Every request
reportOrderUuidemptyTwo-step generate/download tests
fromDate / toDate2026-06-01 / 2026-06-30SQL reports
tenantIdtenant-demoTenant-aware SQL
emailTodeveloper@example.comEmail tests
invoiceNumberRB-EMAIL-001Template and email examples

Use Send and Download for binary PDF/XLSX/ZIP requests. For metadata endpoints, store response.reportOrderUuid in the environment, then call the matching GET endpoint. For Thymeleaf HTML, Postman Preview shows the rendered document.

Collection guideCoverage
report-boot-coreLifecycle, validation and unknown UUID
report-boot-spring-boot-starterAuto-configured provider and order flow
report-boot-jasper / birt / jxls / thymeleafProvider-specific generate and download
report-boot-sql / excel / excel-dashboard / csvDefinitions, formulas, grouping, charts, slices and alternate output
report-boot-designerDesigner JSON request and XLSX attachment
report-boot-emailAttachments, secure links and logs
report-boot-demoRecommended folders and complete integration surface
Capture UUID test
const body = pm.response.json();
pm.environment.set("reportOrderUuid", body.reportOrderUuid);

The Markdown files under docs/postman remain the detailed request oracle. The website cookbooks below translate them into end-to-end developer stories and include the API path beside the Java definition that powers it.

Reference

Reference

Review these topics in order, or jump directly to the card you need.

Complete Configuration

Search every implemented configuration family, default, value shape, and operational meaning.

Searchable property reference

108 of 108 properties shown.

ModulePropertyTypeDefaultExpectedExplanation
Corereport-boot.templates-pathStringclasspath:/report-boot/report-templatesClasspath or filesystem pathBase path used by template providers.
Corereport-boot.default-outputReportOutputPDFProvider-supported outputDefault output when a report does not override it.
Databasereport-boot.database.initialize-schemaBooleantruetrue, falseCreates missing framework schemas, tables, and indexes on startup.
Databasereport-boot.database.schemaStringpublicSafe SQL identifierSchema containing Report-Boot framework tables.
Databasereport-boot.database.table-prefixStringrb_Safe identifier prefixGlobal prefix; each module adds its owned segment.
Storagereport-boot.storage.typeStringfilesystemfilesystemGenerated content storage implementation.
Storagereport-boot.storage.content-rootStringtarget/report-boot/reportsWritable pathRoot directory used by FileSystemReportContentStore.
Ordersreport-boot.orders.typeStringmemorymemory, jdbcDurable JDBC state is required for shared expiry and one-time downloads.
Securityreport-boot.security.enabledBooleantruetrue, falseEnables report lifecycle security behavior.
Securityreport-boot.security.default-expiry-minutesInteger30> 0Default expiry window for generated report orders.
Securityreport-boot.security.max-expiry-minutesInteger1440> 0Upper bound applied to annotation-requested expiry.
Securityreport-boot.security.watermark-enabledBooleantruetrue, falseDefault watermark behavior used by secured reports.
Securityreport-boot.security.one-time-download-enabledBooleanfalsetrue, falseGlobal default for one-time report download claims.
Secure Linksreport-boot.access-token.enabledBooleanfalsetrue, falseIssues and validates Report-Boot signed download tokens.
Secure Linksreport-boot.access-token.issuerStringreport-bootIssuer nameIssuer claim used in Report-Boot download tokens.
Secure Linksreport-boot.access-token.secretStringStrong secret from environmentHMAC secret used to sign Report-Boot download tokens.
Download Pagereport-boot.download-page.enabledBooleantruetrue, falseEnables friendly handling for unavailable downloads.
Download Pagereport-boot.download-page.modeStringrenderrender, redirectRenders the built-in/custom page or redirects to an application URL.
Download Pagereport-boot.download-page.page-locationStringClasspath or file locationOptional custom unavailable-page resource.
Secure Linksreport-boot.download-page.redirect-urlString/report-boot/download-unavailableApplication path or URLWhere expired, used, missing, and forbidden download links redirect.
Download Pagereport-boot.download-page.include-details-in-redirectBooleantruetrue, falseAdds safe reason details to configured redirects.
Download Pagereport-boot.download-page.support-messageStringPlease request a fresh secure link...User-facing textSupport guidance on the default unavailable page.
Diagnosticsreport-boot.diagnostics.include-stack-traceBooleanfalsetrue, falseClean root-cause errors by default; full traces when true.
Governancereport-boot.governance.enabledBooleantruetrue, falseEnables centralized rb_log governance records when configured.
Governancereport-boot.governance.instance-nameStringService/instance identityIdentifies the emitting application instance in governance records.
Starterreport-boot.compilation.compile-on-startupBooleanfalsetrue, falsePrecompile supported templates during application startup.
Starterreport-boot.compilation.fail-on-startup-errorBooleantruetrue, falseInvalid templates fail startup when enabled.
Starterreport-boot.compilation.startup-threadsInteger0>= 0Compilation worker count; zero lets Report-Boot choose.
Excelreport-boot.excel.enabledBooleantruetrue, falseActivates template-free Excel auto-configuration.
SQLreport-boot.sql.enabledBooleantruetrue, falseEnables SQL report auto-configuration when JDBC is available.
SQLreport-boot.sql.file-name-suffixString.xlsxFile extensionSuffix appended to SQL-generated report filenames.
SQLreport-boot.sql.expiry-minutesInteger30> 0Download expiry window for SQL-generated reports.
SQLreport-boot.sql.tenant.columnStringDatabase column nameEnables tenant enforcement for SQL reports.
SQLreport-boot.sql.tenant.parameter-nameStringtenantIdNamed parameterParameter used to pass tenant value into SQL reports.
SQLreport-boot.sql.tenant.detect-from-tokenBooleanfalsetrue, falseReads tenant from current security token when possible.
SQLreport-boot.sql.tenant.token-attribute-nameStringtenant_idJWT or principal attributeClaim or attribute used for tenant detection.
SQL Excelreport-boot.sql.excel.sheet-nameStringReportExcel-safe sheet nameDefault sheet name for generated dynamic Excel reports.
SQL Excelreport-boot.sql.excel.max-rows-per-sheetInteger10485761..1048576Maximum rows per generated sheet.
SQL Excelreport-boot.sql.excel.overflow-policyEnumSPLIT_SHEETSSPLIT_SHEETS or supported policyBehavior when row count exceeds the sheet limit.
SQL Excelreport-boot.sql.excel.window-sizeInteger1000>= 1SXSSF rows retained in memory.
SQL Excelreport-boot.sql.excel.compress-temp-filesBooleantruetrue, falseCompresses temporary files created by streaming Excel.
SQL Excelreport-boot.sql.excel.auto-size-columnsBooleanfalsetrue, falseCalculates column widths from sampled rows when enabled.
SQL Excelreport-boot.sql.excel.max-auto-size-rowsInteger1000>= 0Rows sampled for width calculation.
SQL Excelreport-boot.sql.excel.freeze-headerBooleantruetrue, falseFreezes generated table headers.
SQL Excelreport-boot.sql.excel.auto-filterBooleantruetrue, falseAdds Excel filters to generated headers.
SQL Excelreport-boot.sql.excel.include-metadata-sheetBooleanfalsetrue, falseAdds workbook metadata and dictionary sheet.
SQL Excelreport-boot.sql.excel.metadata-sheet-nameString_Report InfoExcel-safe sheet nameName of the optional metadata sheet.
SQL Excelreport-boot.sql.excel.hide-metadata-sheetBooleanfalsetrue, falseHides metadata while keeping it in the workbook.
CSVreport-boot.csv.enabledBooleantruetrue, falseActivates dynamic CSV rendering.
CSVreport-boot.csv.delimiterString,Single delimiterSeparator written between CSV fields.
CSVreport-boot.csv.include-headerBooleantruetrue, falseWrites rendered column headers.
CSVreport-boot.csv.charsetStringUTF-8Supported charsetEncoding used for generated CSV.
Emailreport-boot.email.enabledBooleantruetrue, falseEnables report email support when dependencies are present.
Emailreport-boot.email.fromStringEmail addressGoverned SMTP sender address.
Emailreport-boot.email.from-nameStringReport-BootDisplay nameGoverned SMTP sender display name.
Emailreport-boot.email.instance-nameStringService/instance identityInstance captured in email governance logs.
Emailreport-boot.email.templates-pathStringclasspath:/report-boot/email-templatesClasspath or filesystem pathEmail template root.
Emailreport-boot.email.fail-when-missing-senderBooleantruetrue, falseFails clearly when no sender is configured.
Emailreport-boot.email.idempotency.enabledBooleantruetrue, falsePrevents duplicate email triggers.
Emailreport-boot.email.idempotency.key-prefixStringreport-emailShort key namespaceNamespaces generated idempotency keys.
Emailreport-boot.email.idempotency.ttlDuration24hSpring DurationRetention window for duplicate reservations.
Emailreport-boot.email.jobs.scheduling-enabledBooleantruetrue, falseDiscovers and schedules @ReportEmailJob beans.
Emailreport-boot.email.jobs.sync-modeStringcreate-missingcreate-missingCreates missing job rows without overwriting operator state.
SMTPREPORT_BOOT_SMTP_FROM_NAMEEnvironmentReport-BootDisplay nameMaps to report-boot.email.from-name in the demo.
SMTPREPORT_BOOT_SMTP_HOSTEnvironmentSMTP hostSMTP server host configured outside source code.
SMTPREPORT_BOOT_SMTP_PORTEnvironment587SMTP portSMTP server port.
SMTPREPORT_BOOT_SMTP_USERNAMEEnvironmentSMTP usernameSMTP account username.
SMTPREPORT_BOOT_SMTP_PASSWORDEnvironmentSMTP/app passwordSMTP credential; keep it secret.
SMTPREPORT_BOOT_SMTP_FROMEnvironmentEmail addressDefault sender address.
SMTPREPORT_BOOT_SMTP_AUTHEnvironmenttruetrue, falseEnables SMTP authentication in the demo.
SMTPREPORT_BOOT_SMTP_STARTTLSEnvironmenttruetrue, falseEnables STARTTLS in the demo.
SMTPREPORT_BOOT_SMTP_CONNECTION_TIMEOUTEnvironment5000MillisecondsSMTP connection timeout.
SMTPREPORT_BOOT_SMTP_TIMEOUTEnvironment5000MillisecondsSMTP read timeout.
SMTPREPORT_BOOT_SMTP_WRITE_TIMEOUTEnvironment5000MillisecondsSMTP write timeout.
Jasperreport-boot.renderer.jasper.enabledBooleantruetrue, falseEnables Jasper provider when JasperReports is on the classpath.
Jasperreport-boot.renderer.jasper.templates-pathStringclasspath:/report-boot/report-templatesClasspath or filesystem pathJasper template root.
Jasperreport-boot.renderer.jasper.cache-compiled-templatesBooleantruetrue, falseCaches compiled Jasper templates.
JXLSreport-boot.renderer.jxls.enabledBooleantruetrue, falseEnables JXLS provider when JXLS is on the classpath.
JXLSreport-boot.renderer.jxls.content-typeStringapplication/vnd...sheetMIME typeContent type returned for JXLS output.
JXLSreport-boot.renderer.jxls.throw-template-exceptionsBooleantruetrue, falseSurfaces template processing failures.
BIRTreport-boot.renderer.birt.enabledBooleantruetrue, falseEnables BIRT provider when BIRT is on the classpath.
BIRTreport-boot.renderer.birt.templates-pathStringclasspath:/report-boot/report-templatesClasspath or filesystem pathBIRT design root.
BIRTreport-boot.renderer.birt.cache-compiled-templatesBooleantruetrue, falseCaches prepared BIRT artifacts.
BIRTreport-boot.renderer.birt.content-typeStringapplication/pdfMIME typeBIRT response content type.
Thymeleafreport-boot.renderer.thymeleaf.enabledBooleantruetrue, falseEnables Thymeleaf provider when Thymeleaf is on the classpath.
Thymeleafreport-boot.renderer.thymeleaf.templates-pathStringclasspath:/report-boot/report-templatesClasspath locationTemplate path for Thymeleaf reports.
Thymeleafreport-boot.renderer.thymeleaf.encodingStringUTF-8Supported encodingTemplate and response encoding.
Thymeleafreport-boot.renderer.thymeleaf.content-typeStringtext/html;charset=UTF-8MIME typeGenerated HTML content type.
Thymeleafreport-boot.renderer.thymeleaf.template-modeStringHTMLThymeleaf modeTemplate parsing mode.
Insightsreport-boot.insights.enabledBooleantruetrue, falseActivates the Insights starter.
Insightsreport-boot.insights.modeStringdb_onlydb_only or supported modeSelects the Insights event pipeline.
Insightsreport-boot.insights.logs.enabledBooleantruetrue, falseCaptures library log events for the console.
Insightsreport-boot.insights.logs.logger-prefixStringcom.reportbootLogger prefixLimits captured logs to Report-Boot packages.
Insightsreport-boot.insights.logs.markerStringREPORT_BOOT_LIBRARYMarker nameMarker used to identify framework log events.
Insightsreport-boot.insights.logs.ring-buffer-sizeInteger1000> 0Recent events retained for SSE subscribers.
AIreport-boot.ai.enabledBooleanfalsetrue, falseActivates AI-assisted designer services.
AIreport-boot.ai.max-prompt-charactersInteger4000> 0Prompt-size guardrail.
AIreport-boot.ai.gemini.api-keyStringSecretServer-side Gemini API key.
AIreport-boot.ai.gemini.default-modelStringgemini-flash-latestAllowed modelDefault model selected by the service.
AIreport-boot.ai.gemini.allowed-modelsList4 configured modelsModel allowlistPrevents arbitrary model selection.
AIreport-boot.ai.gemini.base-urlStringGoogle v1beta URLHTTPS URLGemini API base URL.
AIreport-boot.ai.gemini.request-timeoutDuration45sSpring DurationAI request timeout.
AIreport-boot.ai.gemini.temperatureDouble0.20..1Low-variance design generation.
AIreport-boot.ai.designer-proxy.enabledBooleantruetrue, falseEnables the protected backend proxy.
AIreport-boot.ai.designer-proxy.pathString/api/report-boot/ai/designer/generateApplication pathAI designer proxy endpoint.
AIreport-boot.ai.designer-proxy.require-proxy-tokenBooleantruetrue, falseRequires a proxy token.
AIreport-boot.ai.designer-proxy.token-headerStringX-Report-Boot-AI-TokenHTTP headerHeader carrying the proxy credential.
AIreport-boot.ai.designer-proxy.proxy-tokenStringSecretExpected backend proxy credential.
Recommended for production: keep stack traces off, fail on startup template errors, enforce SQL tenant filtering for multi-tenant systems, compress temp files for large exports.
Remember: annotation reporting and programmable reporting share the same governed lifecycle. JXLS is template-based Excel; report-boot-excel is generated, template-free Excel. window-size controls memory; max-auto-size-rows controls width sampling.

Environment Checklist

Keep secrets and deployment-specific identity outside source control.

Production environment
REPORT_BOOT_DATASOURCE_URL=jdbc:postgresql://db:5432/report_boot
REPORT_BOOT_DATASOURCE_USERNAME=report_boot
REPORT_BOOT_DATASOURCE_PASSWORD=<secret>
REPORT_BOOT_DATABASE_SCHEMA=public
REPORT_BOOT_INSTANCE_NAME=billing-service-01

REPORT_BOOT_STORAGE_CONTENT_ROOT=/var/lib/report-boot/reports
REPORT_BOOT_ACCESS_TOKEN_SECRET=<at-least-32-random-bytes>
REPORT_BOOT_ACCESS_TOKEN_ISSUER=report-boot

REPORT_BOOT_SMTP_HOST=smtp.example.com
REPORT_BOOT_SMTP_PORT=587
REPORT_BOOT_SMTP_USERNAME=reports@example.com
REPORT_BOOT_SMTP_PASSWORD=<smtp-secret-or-app-password>
REPORT_BOOT_SMTP_FROM=reports@example.com
REPORT_BOOT_SMTP_FROM_NAME=Report-Boot
REPORT_BOOT_SMTP_AUTH=true
REPORT_BOOT_SMTP_STARTTLS=true

REPORT_BOOT_AI_GEMINI_API_KEY=<optional-secret>
REPORT_BOOT_AI_PROXY_TOKEN=<optional-secret>
  • Use a shared filesystem/object-store implementation when instances do not share a local volume.
  • Use JDBC orders for expiry and one-time downloads across instances.
  • Rotate token and SMTP secrets through your secret manager.
  • Give each instance a useful name for governance filtering.

Production Checklist

A short review before the first real report leaves the service.

  • Use JDBC report orders and a production DataSource.
  • Choose storage whose content is reachable by every serving instance.
  • Configure tenant filtering for multi-tenant SQL reports.
  • Set maxRows, query timeout, fetch size, and Excel streaming limits.
  • Use an application-specific SecurityProvider and access policy.
  • Use a strong access-token secret and HTTPS links.
  • Use business idempotency keys for scheduled/event emails.
  • Enable governance and verify engine/output/report columns are populated.
  • Disable schema auto-init when formal migrations are mandatory.
  • Test expired, already-used, missing, and forbidden download pages.
  • Test each enabled provider at startup and in CI.

Runtime vs Roadmap

Know what executes today, what is an extension contract, and what remains planned.

The annotation packages intentionally describe a larger enterprise vocabulary than the current runtime. Documentation must preserve that vision without promising behavior that is not wired. Use this status model when evaluating a feature.

StatusDeveloper expectationExamples
Implemented runtimeInstalling the owning module executes the behaviorMapping, required validation, provider selection, SQL, Excel/CSV, email jobs, secure tokens, JDBC orders, governance logging
Implemented with adapterCore contract exists and the application supplies a portCustom ReportBootLogSink, data provider, security manager, content store
Descriptor contractMetadata is extracted; a focused provider/policy adapter must enforce it@ReportCache, @ReportArchive, @ReportPolicy, @ReportWebhook, @ReportMetrics, @ReportPreview
Declaration onlyDo not assume automatic executionEmail-on-event annotations and other advanced event automation not connected to a runtime
Historical planArchitecture/review context, not current APIPhase 1-4 execution plans and early website prompts

@ReportSchedule and the older @ReportEmail metadata describe extension intent. The concrete scheduled-email runtime is @ReportEmailJob + @ReportEmailCondition in report-boot-email, synchronized with the email job/run/log tables.

Ownership and Licensing

The rules that apply when evaluating, redistributing or extending Report-Boot.

TopicPosition
LicenseApache License 2.0 for the Report-Boot codebase unless a file states otherwise
OwnershipCopyright and project attribution remain with the Report-Boot owner
Beta/MVPEvaluate compatibility and operational risk before production adoption
BrandThe software license does not grant unrestricted trademark or brand use
Optional enginesJasperReports, BIRT, JXLS, Apache POI, Thymeleaf and other dependencies retain their own licenses
RedistributionKeep required notices and review THIRD-PARTY-NOTICES for the modules you ship

Provider engines are optional dependencies: the consuming application owns the final dependency stack and must review transitive license and runtime obligations for the providers it installs.

66-Source Coverage Ledger

Every backend Markdown source has an explicit home in this developer guide.

This ledger is the completeness contract for the website documentation. Current runtime sources are merged into module pages and cookbooks; historical plans and website prompts contribute intent only and are never presented as implemented behavior.

Backend sourcePublic topicTreatment
docs/codex-project-context.mdPlatform overview, product map, enterprise visionSynthesized; roadmap claims labeled
docs/designer/all-knowledge.mdDesigner and Excel contract referenceCurrent contracts + design context
docs/designer/examples/consolidated-plan-designer-walkthrough.mdDesigner cookbookRunnable example
docs/designer/README.mdDesigner moduleCurrent
docs/guides/advanced-annotations.mdAnnotation reference and maturityContract status labeled
docs/guides/annotations.mdAnnotation quick start and full referenceCurrent
docs/guides/control-center-log-stream-testing.mdInsights log-stream cookbookCurrent
docs/guides/getting-started.mdFive-minute startCurrent
docs/guides/performance.mdProduction and performanceCurrent
docs/guides/report-boot-governance-log.mdDatabase and governanceCurrent
docs/guides/report-boot-insights-api-contracts.mdInsights API moduleCurrent
docs/guides/report-boot-insights-implementation-spec.mdInsights architecture and operationsImplementation reference
docs/guides/report-email.mdEmail module and cookbooksCurrent
docs/guides/report-email-secure-download-links.mdSecure linksCurrent
docs/guides/security.mdSecurity and lifecycleReconciled with durable current runtime
docs/guides/template-guide.mdTemplate authoringCurrent
docs/phases-execution-plan/phase-1-setup.mdMaturity and roadmapHistorical plan
docs/phases-execution-plan/phase-2-core.mdMaturity and roadmapHistorical plan
docs/phases-execution-plan/phase-3-jasper.mdMaturity and roadmapHistorical plan
docs/phases-execution-plan/phase-4-hardening.mdMaturity and roadmapHistorical plan
docs/postman/postman-collection.mdPostman guide and cookbook indexCurrent
docs/postman/postman-demo.mdTemplate-provider cookbookCurrent
docs/postman/postman-jxls-demo.mdJXLS cookbookCurrent
docs/postman/postman-thymeleaf-demo.mdThymeleaf cookbookCurrent
docs/postman/report-boot-birt.mdBIRT module/cookbookCurrent
docs/postman/report-boot-core.mdCore lifecycle cookbookCurrent
docs/postman/report-boot-csv.mdCSV module/cookbookCurrent
docs/postman/report-boot-demo.mdDemo API mapCurrent
docs/postman/report-boot-designer.mdDesigner cookbookCurrent
docs/postman/report-boot-email.mdEmail cookbooksCurrent
docs/postman/report-boot-excel.mdExcel feature cookbooksCurrent
docs/postman/report-boot-excel-dashboard.mdChart and slice dashboard cookbooksCurrent
docs/postman/report-boot-jasper.mdJasper cookbookCurrent
docs/postman/report-boot-jxls.mdJXLS cookbookCurrent
docs/postman/report-boot-spring-boot-starter.mdStarter smoke testCurrent
docs/postman/report-boot-sql.mdSQL cookbooksCurrent
docs/postman/report-boot-thymeleaf.mdThymeleaf cookbookCurrent
docs/providers/dynamic-table-outputs.mdSQL, Excel and CSV relationshipCurrent
docs/providers/dynamic-tabular-excel.mdDynamic Excel and DesignerCurrent
docs/providers/provider-specification.mdCore provider extensionCurrent contract
docs/providers/sql-reports.mdSQL moduleCurrent
docs/README.mdDocumentation mapReorganized here
docs/reviews/spring-boot-acceptance-review.mdStarter/provider architectureAcceptance rationale
docs/website/lovable-documentation-marketplace-brief.mdProduct positioning and information architectureDesign source; runtime claims verified
docs/website/lovable-updatable-website-prompt.mdWebsite/product directionDesign source
library/OWNERSHIP.mdOwnership and licensingCurrent
library/report-boot-ai/README.mdAI moduleCurrent
library/report-boot-birt/README.mdBIRT moduleCurrent
library/report-boot-core/README.mdCore moduleCurrent
library/report-boot-csv/README.mdCSV moduleCurrent
library/report-boot-demo/README.mdDemo moduleCurrent
library/report-boot-designer/README.mdDesigner moduleCurrent
library/report-boot-email/README.mdEmail moduleCurrent
library/report-boot-email/secure-download-links.mdSecure-link featureCurrent
library/report-boot-excel/CHARTS.mdExcel charts and slicesCurrent
library/report-boot-excel/README.mdExcel module and method dictionaryCurrent
library/report-boot-insights-api/README.mdInsights API moduleCurrent
library/report-boot-insights-spring-boot-starter/README.mdInsights starter moduleCurrent
library/report-boot-jasper/README.mdJasper moduleCurrent
library/report-boot-jxls/README.mdJXLS moduleCurrent
library/report-boot-spring-boot-starter/README.mdStarter, storage, security and governanceCurrent
library/report-boot-sql/README.mdSQL moduleCurrent
library/report-boot-thymeleaf/README.mdThymeleaf moduleCurrent
OWNERSHIP.mdOwnership and attributionCurrent
README.mdExecutive platform/configuration summaryCurrent
THIRD-PARTY-NOTICES.mdThird-party licensingCurrent

Cookbook Index

Start with a user goal, follow the flow, run the API, and inspect the real output.

Annotation Reports: DTO to Download

The shared flow for Core, Starter, Jasper, JXLS, BIRT and Thymeleaf.

How it flows

1Choose provider/template
2Annotate DTO
3POST JSON
4ReportService maps + validates
5Provider renders
6Capture UUID or receive bytes
7Download
InvoiceReportDto.java
@ReportTemplate(
    code = "invoice-basic",
    title = "Basic Invoice",
    templateFile = "classpath:/report-boot/report-templates/invoice-basic.jrxml",
    output = ReportOutput.PDF
)
@ReportEngineType(ReportEngine.JASPER)
@ReportSecured(watermark = true, expiryMinutes = 30)
@ReportFileName("invoice-${invoiceNumber}.pdf")
@ReportAccess(role = "ROLE_REPORT_ADMIN")
@ReportTitle("Invoice Report")
@ReportCategory("Billing")
public class InvoiceReportDto {
    @ReportField("invoiceNumber")
    @ReportRequired
    @ReportSensitive
    private String invoiceNumber;

    @ReportField("customerName")
    @ReportRequired
    private String customerName;

    @ReportField("invoiceDate")
    @ReportDateFormat("yyyy-MM-dd")
    private LocalDate invoiceDate;

    @ReportField("totalAmount")
    @ReportCurrency("USD")
    @ReportFormat(pattern = "#,##0.00")
    private BigDecimal totalAmount;

    @ReportTable("items")
    private List<InvoiceItemDto> items;
}
InvoiceReportController.java
@RestController
@RequestMapping("/api/reports/jasper/invoice")
class InvoiceReportController {
    private final ReportService reportService;

    @PostMapping("/download")
    ResponseEntity<byte[]> download(@RequestBody InvoiceReportDto request) {
        GeneratedReport report = reportService.generate(request);
        return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"" + report.getFileName() + "\"")
            .contentType(MediaType.parseMediaType(report.getContentType()))
            .body(report.getContent());
    }
}
Request body
{
  "invoiceNumber": "INV-2026-1001",
  "customerName": "Acme Corporation",
  "invoiceDate": "2026-07-13",
  "totalAmount": 499.00,
  "items": [
    {
      "itemName": "Report-Boot Enterprise License",
      "quantity": 1,
      "unitPrice": 499.00,
      "total": 499.00
    }
  ]
}
ProviderGenerate metadataImmediate downloadOutput
JasperPOST /api/reports/jasper/invoicePOST /api/reports/jasper/invoice/downloadPDF
JXLSPOST /api/reports/jxls/invoicePOST /api/reports/jxls/invoice/downloadXLSX
BIRTPOST /api/reports/birt/invoicePOST /api/reports/birt/invoice/downloadPDF
ThymeleafPOST /api/reports/thymeleaf/invoicePOST /api/reports/thymeleaf/invoice/downloadHTML
Thymeleaf printPOST /api/reports/thymeleaf/print-invoicePOST /api/reports/thymeleaf/print-invoice/downloadPrint-ready HTML
Generate metadata
curl --location --request POST "http://localhost:8080/api/reports/jasper/invoice" \
+  --header "Content-Type: application/json" \
+  --data '{
  "invoiceNumber": "INV-2026-1001",
  "customerName": "Acme Corporation",
  "invoiceDate": "2026-07-13",
  "totalAmount": 499.00,
  "items": [
    {
      "itemName": "Report-Boot Enterprise License",
      "quantity": 1,
      "unitPrice": 499.00,
      "total": 499.00
    }
  ]
}'
Download captured UUID
curl --location "http://localhost:8080/api/reports/jasper/invoice/{reportOrderUuid}/download" \
+  --header "Accept: application/pdf" \
+  --output invoice.pdf

Switch only the provider segment and Accept type to exercise the same lifecycle with JXLS, BIRT or Thymeleaf. Use immediate-download endpoints when the client needs bytes now; use metadata + UUID when the client needs lifecycle state, later download or email delivery.

SQL Excel or CSV

Run one multi-sheet definition and select the output at the API boundary.

How it flows

1GET with dates/tenant/output
2Load SqlReportDefinition
3Bind named parameters
4Execute trusted SQL
5Render XLSX or CSV ZIP
6Download
Definition
SqlReportSheet invoices = SqlReportSheet.builder()
    .sheetName("Invoices")
    .sqlFile("invoice-report.sql")
    .sortBy("Created On", "Invoice No")
    .excel(excel -> excel
        .header(style -> style
            .backgroundColor(ExcelColors.Section.HEADER_BACKGROUND)
            .fontColor(ExcelColors.Section.HEADER_TEXT)
            .bold(true))
        .column("Customer", column -> column.width(28))
        .column("Total", column -> column.format(CurrencyExcelFormats.USD))
        .formulaColumn("VAT", column -> column
            .round("Total", 2)
            .format(CurrencyExcelFormats.USD))
        .formulaColumn("Grand Total", column -> column
            .SUM("Total", "VAT")
            .format(CurrencyExcelFormats.USD)))
    .build();

SqlReportDefinition definition = SqlReportDefinition.builder()
    .code("invoice-workbook")
    .sheet(invoices)
    .maxRows(500_000)
    .queryTimeoutSeconds(120)
    .fetchSize(1000)
    .build();
Excel curl
curl --location "http://localhost:8080/api/reports/sql/invoices/download?fromDate=2026-06-01&toDate=2026-06-30&tenantId=tenant-demo&output=EXCEL" --output "invoices.xlsx"
CSV curl
curl --location "http://localhost:8080/api/reports/sql/invoices/download?fromDate=2026-06-01&toDate=2026-06-30&tenantId=tenant-demo&output=CSV" --output "invoices.zip"

Formula Playground and Catalog

Download a focused fluent-formula example or the complete 272-function catalog.

How it flows

1GET formula endpoint
2Build calculated columns
3Resolve names to row cells
4Write formulas
5Open formula workbook
Friendly formulas
.formulaColumn("Grand Total", c -> c.SUM("Total", "VAT", "Shipping"))
.formulaColumn("Label", c -> c.concatenate("Customer", "Invoice No"))
.formulaColumn("Rounded", c -> c.round("Total", 2))
curl
curl --location "http://localhost:8080/api/reports/sql/invoices/formulas/download?fromDate=2026-06-01&toDate=2026-06-30&tenantId=tenant-demo" --output "formula-playground.xlsx"

curl --location "http://localhost:8080/api/reports/sql/invoices/formulas/all/download?fromDate=2026-06-01&toDate=2026-06-30&tenantId=tenant-demo" --output "formula-catalog.xlsx"

# Backward-compatible alias
curl --location "http://localhost:8080/api/reports/sql/invoices/quick-formula/download" --output "quick-formula.xlsx"

Grouped, Sorted, and Merged Headers

Generate repeated table sections with isolated summaries and optional parent headers.

How it flows

1GET dates + tenant
2Sort rows
3Group by Customer
4Repeat headers
5Write group totals
6Write grand total
7Download
Core builder
.groupBy("Customer")
.sortBy("Customer", "Created On", "Invoice No")
.betweenGroupSpaceRows(2)
.excel(excel -> excel
    .columnGroup("Invoice", "Invoice No", "Customer", "Created On")
    .columnGroup("Money", "Total", "VAT", "Grand Total")
    .summaryFooter(...))
curl
curl --location "http://localhost:8080/api/reports/sql/invoices/group-sort/download?fromDate=2026-06-01&toDate=2026-06-10&tenantId=tenant-demo" --output "grouped.xlsx"

curl --location "http://localhost:8080/api/reports/sql/invoices/group-headers/download?fromDate=2026-06-01&toDate=2026-06-10&tenantId=tenant-demo" --output "grouped-headers.xlsx"

Nine-Chart Dashboard

Generate source data, KPIs, filters, and all supported chart families on a standard grid.

How it flows

1GET dashboard API
2Execute chart-friendly SQL
3Write Chart Data
4Build dashboard model
5Place 9 charts
6Download XLSX
Chart snippet
.addChart(DynamicExcelLineChart.of(c -> c
    .title("Revenue Trend")
    .categoryColumn("Day Label")
    .valueColumn("Revenue")))
.addChart(DynamicExcelScatterChart.of(c -> c
    .title("Revenue Relationship")
    .categoryColumn("Day No")
    .valueColumn("Revenue")))
curl
curl --location "http://localhost:8080/api/reports/excel/dashboards/invoices/download?fromDate=2026-06-01&toDate=2026-06-30&tenantId=tenant-demo" --output "invoice-dashboard.xlsx"

curl --location "http://localhost:8080/api/reports/excel/dashboards/invoices/filters/download?fromDate=2026-06-01&toDate=2026-06-30&tenantId=tenant-demo" --output "invoice-filter-dashboard.xlsx"

Connected Slice Dashboard

Build an Excel dashboard controlled by Payment Status, Customer, and Day slices.

How it flows

1GET sliced API
2Execute sliced-dashboard SQL
3Write source sheet
4Create connected slice controls
5Connect KPIs/charts
6Download XLSX
Slice snippet
.addSlice(DynamicExcelDropdownSlice.of(s -> s
    .title("Payment Status")
    .column("Payment Status")))
.addSlice(DynamicExcelDropdownSlice.of(s -> s
    .title("Customer")
    .column("Customer")))
.addSlice(DynamicExcelDropdownSlice.of(s -> s
    .title("Day")
    .column("Day Label")))
curl
curl --location "http://localhost:8080/api/reports/excel/dashboards/invoices/sliced/download?fromDate=2026-06-01&toDate=2026-06-30&tenantId=tenant-demo" --output "invoice-sliced-dashboard.xlsx"

Designer JSON to Excel

Post a validated designer contract as JSON or as a JSON attachment.

How it flows

1POST designer JSON
2Validate trusted dataSourceRef
3Build SQL definition
4Generate workbook
5Download XLSX
curl - JSON
curl --location --request POST "http://localhost:8080/api/reports/designer/sql-excel/download" \
  --header "Content-Type: application/json" \
  --data @designer-report.json \
  --output "designer-report.xlsx"
curl - attachment
curl --location --request POST "http://localhost:8080/api/reports/designer/sql-excel/download" \
  --form "file=@designer-report.json;type=application/json" \
  --output "designer-report.xlsx"

AI-Assisted Designer Flow

Ask for a definition, review the proposal, then execute it through the normal trusted pipeline.

How it flows

1Set backend secrets
2POST design prompt
3Receive Designer JSON
4Review dataSourceRef/formulas
5POST approved definition
6Download XLSX
Generate design
curl --location --request POST "http://localhost:8080/api/reports/designer/ai/generate" \
+  --header "Content-Type: application/json" \
+  --header "X-Report-Boot-AI-Token: $REPORT_BOOT_AI_PROXY_TOKEN" \
+  --data '{
    "prompt": "Create an invoice report grouped by customer and date",
    "mode": "design",
    "model": "gemini-flash-latest",
    "currentRequest": null,
    "context": {"templateType": "sql-excel"}
  }'

Review the returned request before execution. Keep dataSourceRef values on an allowlist and do not convert model-proposed arbitrary SQL into a trusted source.

Execute approved request
curl --location --request POST "http://localhost:8080/api/reports/designer/sql-excel/download" \
+  --header "Content-Type: application/json" \
+  --data @approved-designer-request.json \
+  --output designer-report.xlsx

Email Any Provider Attachment

Use one email envelope while the report object selects Jasper, JXLS, BIRT, or Thymeleaf.

How it flows

1POST email request
2Generate selected provider report
3Render email template
4Reserve idempotency key
5Send attachment
6Write email + central logs
Request body
{
  "to": ["developer@example.com"],
  "cc": [],
  "bcc": [],
  "subject": "Your invoice report is ready",
  "templateName": "invoice-report-ready",
  "idempotencyKey": "invoice-INV-2026-1001-v1",
  "report": {
  "invoiceNumber": "INV-2026-1001",
  "customerName": "Acme Corporation",
  "invoiceDate": "2026-07-13",
  "totalAmount": 499.00,
  "items": [
    {
      "itemName": "Report-Boot Enterprise License",
      "quantity": 1,
      "unitPrice": 499.00,
      "total": 499.00
    }
  ]
}
}
curl
curl --location --request POST "http://localhost:8080/api/reports/email/jasper/invoice" \
  --header "Content-Type: application/json" \
  --data '{
  "to": ["developer@example.com"],
  "cc": [],
  "bcc": [],
  "subject": "Your invoice report is ready",
  "templateName": "invoice-report-ready",
  "idempotencyKey": "invoice-INV-2026-1001-v1",
  "report": {
  "invoiceNumber": "INV-2026-1001",
  "customerName": "Acme Corporation",
  "invoiceDate": "2026-07-13",
  "totalAmount": 499.00,
  "items": [
    {
      "itemName": "Report-Boot Enterprise License",
      "quantity": 1,
      "unitPrice": 499.00,
      "total": 499.00
    }
  ]
}
}'

# Change only the provider path:
# /jxls/invoice
# /birt/invoice
# /thymeleaf/invoice

Scheduled Conditional Email

Let the annotated Spring bean register on startup and remain governable from the database.

How it flows

1Start application
2Discover DailyInvoiceEmailJob
3Create rb_email_job
4Cron fires
5Check enabled + totalAmount > 0
6Send once across instances
7Inspect run/log
Demo annotation
@ReportEmailJob(
    key = "demo-daily-invoice-email",
    name = "Demo Daily Invoice Email",
    cron = "0 0 8 * * *",
    subject = "Daily invoice report",
    template = "daily-invoice-email"
)
@ReportEmailCondition(
    field = "totalAmount",
    operator = ReportEmailConditionOperator.GREATER_THAN,
    value = "0"
)
Inspect governance
select * from public.rb_email_job where job_key = 'demo-daily-invoice-email';
select * from public.rb_email_run order by started_at desc;
select * from public.rb_email_log order by finished_at desc;

Persist and Stream Library Logs

Verify durable logs first, then open SSE and watch filtered events in real time.

How it flows

1Install insights starter
2Provide ReportBootLogSink
3Run Control Center
4Query recent JSON
5Open SSE
6Emit test event
7Inspect Insights table/console
1. Recent stored logs
curl.exe -i -H "Accept: application/json" "http://localhost:8085/api/control/v1/logs/recent?limit=20"
2. Keep SSE request open
curl.exe -i -N -H "Accept: text/event-stream" "http://localhost:8085/api/control/v1/logs/stream"
3. Emit a filterable error
curl.exe -i -X POST "http://localhost:8085/api/control/v1/logs/emit?level=ERROR&count=1&message=seeded-error&correlation-id=cid_12ab&report-name=invoice-basic&template-code=invoice-basic&error-stack=java.lang.RuntimeException%3A+boom"
ViewUse it forFilters/details
Recent JSONProve database persistence and API healthlimit, level, correlationId, reportName, loggerName, marker, threadName
SSE streamWatch new events without pollingAccept: text/event-stream is mandatory; omission can return 406
Insights tableScan, paginate and expand structured recordsCorrelation, report/template, logger, marker, thread, level, errors-only
Insights consoleConsole-like top-to-bottom streamColored levels; newest records arrive at the bottom
rb_logDurable report business/governance ledgerReport code, user, engine/output, file, duration and error

Open the Insights application at /audit-logs, then choose Library Logs Stream. A console event and an rb_log row serve different jobs: runtime diagnosis versus durable report governance.

Configuration Templates

Copy the dependency stack and YAML for one capability, then understand every property before changing it.

These are complete capability templates, not one oversized application.yml. Start with Core & Starter, then add only the provider or feature templates your service needs. Environment variables hold secrets and deployment-specific values; YAML holds safe defaults and framework behavior.

TemplateLibraries installedConfiguration coverage
Core & Starterreport-boot-spring-boot-starterLifecycle, database, storage, security, tokens, unavailable page, compilation and governance
Jasperstarter + report-boot-jasperJRXML provider and template cache
JXLSstarter + report-boot-jxlsDesigned XLSX provider
BIRTstarter + report-boot-birtRPTDESIGN provider
Thymeleafstarter + report-boot-thymeleafHTML and print-ready templates
SQLstarter + report-boot-sqlTrusted query execution and tenant resolution
Excelstarter + SQL + report-boot-excelDynamic XLSX and streaming defaults
CSVstarter + SQL + report-boot-csvDelimited and multi-sheet ZIP output
Emailstarter + email + a rendererSMTP, templates, idempotency and jobs
Insightsinsights API + insights starterLog capture and sink forwarding
Designerdesigner + SQL + ExcelVisual JSON contract; no dedicated prefix
AIAI + DesignerGemini and secured designer proxy

The dictionaries below cover all 108 properties and environment settings in the current consolidated reference. Each row explains its default, accepted value, and operational purpose.

Core & Starter Configuration

The production baseline for lifecycle state, content storage, security, governance and provider discovery.

Maven dependencies

1 library
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-spring-boot-starter</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
report-boot:
  templates-path: classpath:/report-boot/report-templates
  default-output: PDF

  database:
    initialize-schema: true
    schema: public
    table-prefix: rb_

  orders:
    type: jdbc

  storage:
    type: filesystem
    content-root: /var/report-boot/reports

  security:
    enabled: true
    default-expiry-minutes: 30
    max-expiry-minutes: 1440
    watermark-enabled: true
    one-time-download-enabled: false

  access-token:
    enabled: true
    issuer: report-boot
    secret: ${REPORT_BOOT_ACCESS_TOKEN_SECRET}

  download-page:
    enabled: true
    mode: render
    page-location: ""
    redirect-url: /report-boot/download-unavailable
    include-details-in-redirect: true
    support-message: Please request a fresh secure link from the application.

  compilation:
    compile-on-startup: false
    fail-on-startup-error: true
    startup-threads: 0

  diagnostics:
    include-stack-trace: false

  governance:
    enabled: true
    instance-name: ${REPORT_BOOT_INSTANCE_NAME:report-boot-app}
Implementation note: Use JDBC orders and a shared content root for multiple instances. Keep the access-token secret identical across instances and never commit it.

Property dictionary

Defaults, accepted values, and when each setting matters.

28 documented settings
PropertyTypeDefaultAccepted valueWhat it controls / when to change
Corereport-boot.templates-pathStringclasspath:/report-boot/report-templatesClasspath or filesystem pathBase path used by template providers.
Corereport-boot.default-outputReportOutputPDFProvider-supported outputDefault output when a report does not override it.
Databasereport-boot.database.initialize-schemaBooleantruetrue, falseCreates missing framework schemas, tables, and indexes on startup.
Databasereport-boot.database.schemaStringpublicSafe SQL identifierSchema containing Report-Boot framework tables.
Databasereport-boot.database.table-prefixStringrb_Safe identifier prefixGlobal prefix; each module adds its owned segment.
Storagereport-boot.storage.typeStringfilesystemfilesystemGenerated content storage implementation.
Storagereport-boot.storage.content-rootStringtarget/report-boot/reportsWritable pathRoot directory used by FileSystemReportContentStore.
Ordersreport-boot.orders.typeStringmemorymemory, jdbcDurable JDBC state is required for shared expiry and one-time downloads.
Securityreport-boot.security.enabledBooleantruetrue, falseEnables report lifecycle security behavior.
Securityreport-boot.security.default-expiry-minutesInteger30> 0Default expiry window for generated report orders.
Securityreport-boot.security.max-expiry-minutesInteger1440> 0Upper bound applied to annotation-requested expiry.
Securityreport-boot.security.watermark-enabledBooleantruetrue, falseDefault watermark behavior used by secured reports.
Securityreport-boot.security.one-time-download-enabledBooleanfalsetrue, falseGlobal default for one-time report download claims.
Secure Linksreport-boot.access-token.enabledBooleanfalsetrue, falseIssues and validates Report-Boot signed download tokens.
Secure Linksreport-boot.access-token.issuerStringreport-bootIssuer nameIssuer claim used in Report-Boot download tokens.
Secure Linksreport-boot.access-token.secretStringNot setStrong secret from environmentHMAC secret used to sign Report-Boot download tokens.
Download Pagereport-boot.download-page.enabledBooleantruetrue, falseEnables friendly handling for unavailable downloads.
Download Pagereport-boot.download-page.modeStringrenderrender, redirectRenders the built-in/custom page or redirects to an application URL.
Download Pagereport-boot.download-page.page-locationStringNot setClasspath or file locationOptional custom unavailable-page resource.
Secure Linksreport-boot.download-page.redirect-urlString/report-boot/download-unavailableApplication path or URLWhere expired, used, missing, and forbidden download links redirect.
Download Pagereport-boot.download-page.include-details-in-redirectBooleantruetrue, falseAdds safe reason details to configured redirects.
Download Pagereport-boot.download-page.support-messageStringPlease request a fresh secure link...User-facing textSupport guidance on the default unavailable page.
Diagnosticsreport-boot.diagnostics.include-stack-traceBooleanfalsetrue, falseClean root-cause errors by default; full traces when true.
Governancereport-boot.governance.enabledBooleantruetrue, falseEnables centralized rb_log governance records when configured.
Governancereport-boot.governance.instance-nameStringNot setService/instance identityIdentifies the emitting application instance in governance records.
Starterreport-boot.compilation.compile-on-startupBooleanfalsetrue, falsePrecompile supported templates during application startup.
Starterreport-boot.compilation.fail-on-startup-errorBooleantruetrue, falseInvalid templates fail startup when enabled.
Starterreport-boot.compilation.startup-threadsInteger0>= 0Compilation worker count; zero lets Report-Boot choose.

Jasper Configuration

Enable JRXML-backed PDF rendering and choose how compiled templates are resolved and cached.

Maven dependencies

2 libraries
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-spring-boot-starter</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-jasper</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
report-boot:
  renderer:
    jasper:
      enabled: true
      templates-path: classpath:/report-boot/report-templates
      cache-compiled-templates: true
Implementation note: Add the Core & Starter compilation template when JRXML files must be validated during deployment.

Property dictionary

Defaults, accepted values, and when each setting matters.

3 documented settings
PropertyTypeDefaultAccepted valueWhat it controls / when to change
Jasperreport-boot.renderer.jasper.enabledBooleantruetrue, falseEnables Jasper provider when JasperReports is on the classpath.
Jasperreport-boot.renderer.jasper.templates-pathStringclasspath:/report-boot/report-templatesClasspath or filesystem pathJasper template root.
Jasperreport-boot.renderer.jasper.cache-compiled-templatesBooleantruetrue, falseCaches compiled Jasper templates.

JXLS Configuration

Populate analyst-designed XLSX templates while preserving normal Report-Boot lifecycle behavior.

Maven dependencies

2 libraries
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-spring-boot-starter</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-jxls</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
report-boot:
  renderer:
    jxls:
      enabled: true
      content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
      throw-template-exceptions: true
Implementation note: Keep template exceptions enabled during development and CI so broken expressions fail visibly.

Property dictionary

Defaults, accepted values, and when each setting matters.

3 documented settings
PropertyTypeDefaultAccepted valueWhat it controls / when to change
JXLSreport-boot.renderer.jxls.enabledBooleantruetrue, falseEnables JXLS provider when JXLS is on the classpath.
JXLSreport-boot.renderer.jxls.content-typeStringapplication/vnd...sheetMIME typeContent type returned for JXLS output.
JXLSreport-boot.renderer.jxls.throw-template-exceptionsBooleantruetrue, falseSurfaces template processing failures.

BIRT Configuration

Enable RPTDESIGN-backed PDF rendering when the BIRT runtime is available.

Maven dependencies

2 libraries
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-spring-boot-starter</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-birt</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
report-boot:
  renderer:
    birt:
      enabled: true
      templates-path: classpath:/report-boot/report-templates
      cache-compiled-templates: true
      content-type: application/pdf
Implementation note: The provider activates only when the BIRT engine classes are present on the runtime classpath.

Property dictionary

Defaults, accepted values, and when each setting matters.

4 documented settings
PropertyTypeDefaultAccepted valueWhat it controls / when to change
BIRTreport-boot.renderer.birt.enabledBooleantruetrue, falseEnables BIRT provider when BIRT is on the classpath.
BIRTreport-boot.renderer.birt.templates-pathStringclasspath:/report-boot/report-templatesClasspath or filesystem pathBIRT design root.
BIRTreport-boot.renderer.birt.cache-compiled-templatesBooleantruetrue, falseCaches prepared BIRT artifacts.
BIRTreport-boot.renderer.birt.content-typeStringapplication/pdfMIME typeBIRT response content type.

Thymeleaf Configuration

Render normal and print-ready HTML from the shared annotation DTO model.

Maven dependencies

2 libraries
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-spring-boot-starter</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-thymeleaf</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
report-boot:
  renderer:
    thymeleaf:
      enabled: true
      templates-path: classpath:/report-boot/report-templates
      encoding: UTF-8
      content-type: text/html;charset=UTF-8
      template-mode: HTML
Implementation note: Keep encoding and response content type aligned; mismatches usually appear as corrupted non-ASCII report text.

Property dictionary

Defaults, accepted values, and when each setting matters.

5 documented settings
PropertyTypeDefaultAccepted valueWhat it controls / when to change
Thymeleafreport-boot.renderer.thymeleaf.enabledBooleantruetrue, falseEnables Thymeleaf provider when Thymeleaf is on the classpath.
Thymeleafreport-boot.renderer.thymeleaf.templates-pathStringclasspath:/report-boot/report-templatesClasspath locationTemplate path for Thymeleaf reports.
Thymeleafreport-boot.renderer.thymeleaf.encodingStringUTF-8Supported encodingTemplate and response encoding.
Thymeleafreport-boot.renderer.thymeleaf.content-typeStringtext/html;charset=UTF-8MIME typeGenerated HTML content type.
Thymeleafreport-boot.renderer.thymeleaf.template-modeStringHTMLThymeleaf modeTemplate parsing mode.

SQL Configuration

Configure trusted SQL report execution, output naming, expiry and optional tenant enforcement.

Maven dependencies

2 libraries
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-spring-boot-starter</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-sql</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
report-boot:
  sql:
    enabled: true
    file-name-suffix: .xlsx
    expiry-minutes: 30
    tenant:
      column: tenant_id
      parameter-name: tenantId
      detect-from-token: false
      token-attribute-name: tenant_id
Implementation note: Leave tenant.column empty only for genuinely non-tenant data. Never accept raw SQL text from an untrusted HTTP request.

Property dictionary

Defaults, accepted values, and when each setting matters.

7 documented settings
PropertyTypeDefaultAccepted valueWhat it controls / when to change
SQLreport-boot.sql.enabledBooleantruetrue, falseEnables SQL report auto-configuration when JDBC is available.
SQLreport-boot.sql.file-name-suffixString.xlsxFile extensionSuffix appended to SQL-generated report filenames.
SQLreport-boot.sql.expiry-minutesInteger30> 0Download expiry window for SQL-generated reports.
SQLreport-boot.sql.tenant.columnStringNot setDatabase column nameEnables tenant enforcement for SQL reports.
SQLreport-boot.sql.tenant.parameter-nameStringtenantIdNamed parameterParameter used to pass tenant value into SQL reports.
SQLreport-boot.sql.tenant.detect-from-tokenBooleanfalsetrue, falseReads tenant from current security token when possible.
SQLreport-boot.sql.tenant.token-attribute-nameStringtenant_idJWT or principal attributeClaim or attribute used for tenant detection.

Excel Configuration

Configure template-free XLSX generation, streaming memory, sheet limits, filters and metadata.

Maven dependencies

3 libraries
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-spring-boot-starter</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-sql</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-excel</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
report-boot:
  excel:
    enabled: true

  sql:
    excel:
      sheet-name: Report
      max-rows-per-sheet: 1048576
      overflow-policy: SPLIT_SHEETS
      window-size: 1000
      compress-temp-files: true
      auto-size-columns: false
      max-auto-size-rows: 1000
      freeze-header: true
      auto-filter: true
      include-metadata-sheet: true
      metadata-sheet-name: _Report Info
      hide-metadata-sheet: false
Implementation note: window-size controls rows retained in memory; max-auto-size-rows controls width sampling. They solve different performance problems.

Property dictionary

Defaults, accepted values, and when each setting matters.

13 documented settings
PropertyTypeDefaultAccepted valueWhat it controls / when to change
Excelreport-boot.excel.enabledBooleantruetrue, falseActivates template-free Excel auto-configuration.
SQL Excelreport-boot.sql.excel.sheet-nameStringReportExcel-safe sheet nameDefault sheet name for generated dynamic Excel reports.
SQL Excelreport-boot.sql.excel.max-rows-per-sheetInteger10485761..1048576Maximum rows per generated sheet.
SQL Excelreport-boot.sql.excel.overflow-policyEnumSPLIT_SHEETSSPLIT_SHEETS or supported policyBehavior when row count exceeds the sheet limit.
SQL Excelreport-boot.sql.excel.window-sizeInteger1000>= 1SXSSF rows retained in memory.
SQL Excelreport-boot.sql.excel.compress-temp-filesBooleantruetrue, falseCompresses temporary files created by streaming Excel.
SQL Excelreport-boot.sql.excel.auto-size-columnsBooleanfalsetrue, falseCalculates column widths from sampled rows when enabled.
SQL Excelreport-boot.sql.excel.max-auto-size-rowsInteger1000>= 0Rows sampled for width calculation.
SQL Excelreport-boot.sql.excel.freeze-headerBooleantruetrue, falseFreezes generated table headers.
SQL Excelreport-boot.sql.excel.auto-filterBooleantruetrue, falseAdds Excel filters to generated headers.
SQL Excelreport-boot.sql.excel.include-metadata-sheetBooleanfalsetrue, falseAdds workbook metadata and dictionary sheet.
SQL Excelreport-boot.sql.excel.metadata-sheet-nameString_Report InfoExcel-safe sheet nameName of the optional metadata sheet.
SQL Excelreport-boot.sql.excel.hide-metadata-sheetBooleanfalsetrue, falseHides metadata while keeping it in the workbook.

CSV Configuration

Configure portable delimited output from the same tabular definition used by Dynamic Excel.

Maven dependencies

3 libraries
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-spring-boot-starter</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-sql</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-csv</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
report-boot:
  csv:
    enabled: true
    delimiter: ","
    include-header: true
    charset: UTF-8
Implementation note: A one-sheet definition returns one CSV. Multiple sheets return a ZIP containing one CSV per sheet.

Property dictionary

Defaults, accepted values, and when each setting matters.

4 documented settings
PropertyTypeDefaultAccepted valueWhat it controls / when to change
CSVreport-boot.csv.enabledBooleantruetrue, falseActivates dynamic CSV rendering.
CSVreport-boot.csv.delimiterString,Single delimiterSeparator written between CSV fields.
CSVreport-boot.csv.include-headerBooleantruetrue, falseWrites rendered column headers.
CSVreport-boot.csv.charsetStringUTF-8Supported charsetEncoding used for generated CSV.

Email & SMTP Configuration

Configure report attachments, HTML email templates, scheduled jobs and duplicate-send protection.

Maven dependencies

3 libraries
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-spring-boot-starter</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-email</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-thymeleaf</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
spring:
  mail:
    host: ${REPORT_BOOT_SMTP_HOST}
    port: ${REPORT_BOOT_SMTP_PORT:587}
    username: ${REPORT_BOOT_SMTP_USERNAME}
    password: ${REPORT_BOOT_SMTP_PASSWORD}
    properties:
      mail.smtp.auth: ${REPORT_BOOT_SMTP_AUTH:true}
      mail.smtp.starttls.enable: ${REPORT_BOOT_SMTP_STARTTLS:true}
      mail.smtp.connectiontimeout: ${REPORT_BOOT_SMTP_CONNECTION_TIMEOUT:5000}
      mail.smtp.timeout: ${REPORT_BOOT_SMTP_TIMEOUT:5000}
      mail.smtp.writetimeout: ${REPORT_BOOT_SMTP_WRITE_TIMEOUT:5000}

report-boot:
  email:
    enabled: true
    from: ${REPORT_BOOT_SMTP_FROM}
    from-name: ${REPORT_BOOT_SMTP_FROM_NAME:Report-Boot}
    instance-name: ${REPORT_BOOT_INSTANCE_NAME:report-boot-app}
    templates-path: classpath:/report-boot/email-templates
    fail-when-missing-sender: true
    idempotency:
      enabled: true
      key-prefix: report-email
      ttl: 24h
    jobs:
      scheduling-enabled: true
      sync-mode: create-missing
Implementation note: Use an SMTP app password or secret manager value. create-missing preserves operator changes to database-backed job activation and schedules.

Property dictionary

Defaults, accepted values, and when each setting matters.

22 documented settings
PropertyTypeDefaultAccepted valueWhat it controls / when to change
Emailreport-boot.email.enabledBooleantruetrue, falseEnables report email support when dependencies are present.
Emailreport-boot.email.fromStringNot setEmail addressGoverned SMTP sender address.
Emailreport-boot.email.from-nameStringReport-BootDisplay nameGoverned SMTP sender display name.
Emailreport-boot.email.instance-nameStringNot setService/instance identityInstance captured in email governance logs.
Emailreport-boot.email.templates-pathStringclasspath:/report-boot/email-templatesClasspath or filesystem pathEmail template root.
Emailreport-boot.email.fail-when-missing-senderBooleantruetrue, falseFails clearly when no sender is configured.
Emailreport-boot.email.idempotency.enabledBooleantruetrue, falsePrevents duplicate email triggers.
Emailreport-boot.email.idempotency.key-prefixStringreport-emailShort key namespaceNamespaces generated idempotency keys.
Emailreport-boot.email.idempotency.ttlDuration24hSpring DurationRetention window for duplicate reservations.
Emailreport-boot.email.jobs.scheduling-enabledBooleantruetrue, falseDiscovers and schedules @ReportEmailJob beans.
Emailreport-boot.email.jobs.sync-modeStringcreate-missingcreate-missingCreates missing job rows without overwriting operator state.
SMTPREPORT_BOOT_SMTP_FROM_NAMEEnvironmentReport-BootDisplay nameMaps to report-boot.email.from-name in the demo.
SMTPREPORT_BOOT_SMTP_HOSTEnvironmentNot setSMTP hostSMTP server host configured outside source code.
SMTPREPORT_BOOT_SMTP_PORTEnvironment587SMTP portSMTP server port.
SMTPREPORT_BOOT_SMTP_USERNAMEEnvironmentNot setSMTP usernameSMTP account username.
SMTPREPORT_BOOT_SMTP_PASSWORDEnvironmentNot setSMTP/app passwordSMTP credential; keep it secret.
SMTPREPORT_BOOT_SMTP_FROMEnvironmentNot setEmail addressDefault sender address.
SMTPREPORT_BOOT_SMTP_AUTHEnvironmenttruetrue, falseEnables SMTP authentication in the demo.
SMTPREPORT_BOOT_SMTP_STARTTLSEnvironmenttruetrue, falseEnables STARTTLS in the demo.
SMTPREPORT_BOOT_SMTP_CONNECTION_TIMEOUTEnvironment5000MillisecondsSMTP connection timeout.
SMTPREPORT_BOOT_SMTP_TIMEOUTEnvironment5000MillisecondsSMTP read timeout.
SMTPREPORT_BOOT_SMTP_WRITE_TIMEOUTEnvironment5000MillisecondsSMTP write timeout.

Insights Configuration

Capture Report-Boot library logs and forward structured entries to the application-owned sink.

Maven dependencies

2 libraries
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-insights-api</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-insights-spring-boot-starter</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
report-boot:
  insights:
    enabled: true
    mode: db_only
    logs:
      enabled: true
      logger-prefix: com.reportboot
      marker: REPORT_BOOT_LIBRARY
      ring-buffer-size: 1000
Implementation note: A ReportBootLogSink bean is still required for persistence. The ring buffer supports recent/live events; it is not durable storage.

Property dictionary

Defaults, accepted values, and when each setting matters.

6 documented settings
PropertyTypeDefaultAccepted valueWhat it controls / when to change
Insightsreport-boot.insights.enabledBooleantruetrue, falseActivates the Insights starter.
Insightsreport-boot.insights.modeStringdb_onlydb_only or supported modeSelects the Insights event pipeline.
Insightsreport-boot.insights.logs.enabledBooleantruetrue, falseCaptures library log events for the console.
Insightsreport-boot.insights.logs.logger-prefixStringcom.reportbootLogger prefixLimits captured logs to Report-Boot packages.
Insightsreport-boot.insights.logs.markerStringREPORT_BOOT_LIBRARYMarker nameMarker used to identify framework log events.
Insightsreport-boot.insights.logs.ring-buffer-sizeInteger1000> 0Recent events retained for SSE subscribers.

Designer Configuration

Install the JSON definition layer with the SQL executor and Excel renderer it delegates to.

Maven dependencies

3 libraries
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-designer</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-sql</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-excel</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
report-boot:
  sql:
    enabled: true
  excel:
    enabled: true

# Application-owned trusted source registry:
# invoice_data -> classpath:/report-boot/sql/invoice-report.sql
Implementation note: report-boot-designer has no dedicated configuration prefix. Configure its runtime partners and provide DesignerSqlExcelDataSourceRegistry when the UI uses dataSourceRef.

Property dictionary

Defaults, accepted values, and when each setting matters.

0 documented settings
This contract module has no dedicated configuration prefix. Its behavior comes from the runtime libraries shown above and from application-provided beans.

AI Configuration

Secure the server-side Gemini bridge, constrain model selection and keep provider credentials out of the browser.

Maven dependencies

2 libraries
pom.xml
<dependencies>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-ai</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
  <dependency>
    <groupId>com.reportboot</groupId>
    <artifactId>report-boot-designer</artifactId>
    <version>0.1.0-MVP</version>
  </dependency>
</dependencies>

Spring configuration

Copy-ready
application.yml
report-boot:
  ai:
    enabled: ${REPORT_BOOT_AI_ENABLED:false}
    max-prompt-characters: 4000
    gemini:
      api-key: ${REPORT_BOOT_AI_GEMINI_API_KEY}
      default-model: gemini-flash-latest
      allowed-models:
        - gemini-flash-latest
        - gemini-2.5-flash
        - gemini-2.5-flash-lite
        - gemini-pro-latest
      base-url: https://generativelanguage.googleapis.com/v1beta
      request-timeout: 45s
      temperature: 0.2
    designer-proxy:
      enabled: true
      path: /api/report-boot/ai/designer/generate
      require-proxy-token: ${REPORT_BOOT_AI_REQUIRE_PROXY_TOKEN:true}
      token-header: X-Report-Boot-AI-Token
      proxy-token: ${REPORT_BOOT_AI_PROXY_TOKEN}
Implementation note: Production must require a proxy token. AI produces a proposed Designer definition; applications must still validate trusted dataSourceRef values before execution.

Property dictionary

Defaults, accepted values, and when each setting matters.

13 documented settings
PropertyTypeDefaultAccepted valueWhat it controls / when to change
AIreport-boot.ai.enabledBooleanfalsetrue, falseActivates AI-assisted designer services.
AIreport-boot.ai.max-prompt-charactersInteger4000> 0Prompt-size guardrail.
AIreport-boot.ai.gemini.api-keyStringNot setSecretServer-side Gemini API key.
AIreport-boot.ai.gemini.default-modelStringgemini-flash-latestAllowed modelDefault model selected by the service.
AIreport-boot.ai.gemini.allowed-modelsList4 configured modelsModel allowlistPrevents arbitrary model selection.
AIreport-boot.ai.gemini.base-urlStringGoogle v1beta URLHTTPS URLGemini API base URL.
AIreport-boot.ai.gemini.request-timeoutDuration45sSpring DurationAI request timeout.
AIreport-boot.ai.gemini.temperatureDouble0.20..1Low-variance design generation.
AIreport-boot.ai.designer-proxy.enabledBooleantruetrue, falseEnables the protected backend proxy.
AIreport-boot.ai.designer-proxy.pathString/api/report-boot/ai/designer/generateApplication pathAI designer proxy endpoint.
AIreport-boot.ai.designer-proxy.require-proxy-tokenBooleantruetrue, falseRequires a proxy token.
AIreport-boot.ai.designer-proxy.token-headerStringX-Report-Boot-AI-TokenHTTP headerHeader carrying the proxy credential.
AIreport-boot.ai.designer-proxy.proxy-tokenStringNot setSecretExpected backend proxy credential.