Skip to content

Architecture

Components

flowchart LR
    B[Browser or GIS client] --> A[Apache]
    A --> P[PHP Jasper service]
    P --> J[Tomcat 9 report WAR]
    P --> D[(Jasper application PostgreSQL)]
    P --> C[(Central PostgreSQL)]
    P --> F[Report JSON / JRXML / assets / output]
    J --> R[(Report datasource PostgreSQL)]
    P --> M[Mail relay or PHP mail]
    S[systemd timer] --> CLI[PHP schedule CLI]
    CLI --> J
    CLI --> D
    CLI --> F
    CLI --> M

Apache exposes the PHP application and, in the installer configuration, proxies /report and /acugis_report_image directly to Tomcat. Current UI report execution normally uses reports/execute_report.php, which validates report ACLs before making a server-side request to Tomcat.

Directory layout

Path Architectural responsibility
api/ Report/datasource registries, ACL-filtered discovery, and resource synchronization
reports/ Management UI, report definition storage helpers, viewer, and execution proxy
lib/ Shared bootstrap, PostgreSQL, auth/ACL, repositories, scheduler, systemd, and mail logic
action/ Form-backed JSON mutations for schedules, recipients, and legacy templates
database/ Fresh-install PostgreSQL DDL
docker/report-server/ Tomcat image/Compose definitions, WAR/JDBC mounts, JNDI context, and report artifacts
scripts/ CLI schedule runner and Central resource sync
schedules/, systemd/ Generated scheduler state, logs, outputs, services, and timers
assets/reports/, email_tmpl/ Thumbnails and file-backed message templates
deploy/ Apache/Central reverse-proxy example

Request and authentication flow

sequenceDiagram
    participant Client
    participant PHP
    participant Central as Central PostgreSQL
    participant AppDB as Application PostgreSQL
    participant Jasper as Tomcat/WAR

    Client->>PHP: HTTP request + optional acugis_session
    PHP->>Central: SHA-256 cookie lookup (when auth DSN resolves)
    Central-->>PHP: user and groups
    PHP->>Central: service/report permission query
    alt registry or metadata request
        PHP->>AppDB: Read datasource metadata when needed
        PHP-->>Client: JSON
    else report execution
        PHP->>Jasper: Server-side request after ACL check
        Jasper-->>PHP: Exported report
        PHP-->>Client: Forwarded representation
    end

When no Central DSN resolves, auth helpers deliberately bypass checks and install a synthetic local administrator for login-required flows. When a DSN resolves but is unavailable, guarded requests fail closed with 503.

Report lifecycle

sequenceDiagram
    participant U as Authorized user
    participant PHP as PHP service
    participant DB as App PostgreSQL
    participant FS as Filesystem
    participant C as Central PostgreSQL
    participant T as Tomcat/Jasper

    U->>PHP: Publish JRXML and metadata
    PHP->>DB: Read datasource
    PHP->>FS: Write .report.json, .jrxml, optional .jasper/.png
    PHP->>C: Register resource and default ACL
    U->>PHP: Run report
    PHP->>C: Validate session/report permission
    PHP->>T: Forward _repName, _dataSource, format, parameters
    T->>DB: JNDI lookup is generated from datasource rows
    T-->>PHP: Rendered content
    PHP-->>U: Proxied response

Publishing tries jasperstarter compile when no compiled file is uploaded. Compilation failure is nonfatal; a .jasper may be supplied separately.

Data and storage boundaries

  • Application metadata: the five tables from database/schema.sql.
  • Report definitions: reports/json/*.report.json.
  • Report artifacts: docker/report-server/reports/*.jrxml and *.jasper.
  • Thumbnails: assets/reports/<report>.png; the serving endpoint always declares image/png.
  • Datasource credentials: clear text in jasper_datasource, then clear text in generated Tomcat XML.
  • Email templates: files under email_tmpl/, not application DB rows.
  • Schedule EnvironmentFiles/logs/output: schedules/.
  • Central identity/ACL: external Central tables, not owned by this schema.

The datasource loader has a legacy fallback to an application-schema pg_store table when jasper_datasource is absent, but schema.sql does not create pg_store.

Database interactions and caching

PHP opens PostgreSQL connections through pg_connect() and uses parameterized queries for application/auth mutations and lookups. It does not use persistent PHP connections or define an application connection pool. The generated Tomcat JNDI resources use Tomcat JDBC pooling (maxTotal=20, maxIdle=10, maxWaitMillis=10000, SELECT 1 validation on borrow).

No Redis, Memcached, shared application cache, or report-result cache is implemented. The scheduler-column presence check is cached only in a PHP static variable for the current process/request. Thumbnail responses advertise a private one-hour browser cache, and the execution proxy forwards selected upstream cache headers.

Authorization

  • Service administration uses Central resource type service, key jasper_reports.
  • Individual reports use resource type jasper_report and the report key.
  • New report resources receive Administrators=admin, Editors=edit, and Public=view only where those Central groups exist.
  • Runtime anonymous requests can receive implicit Public access when Central auth is enabled.
  • Scheduling and recipient administration require a platform administrator, not only a report editor.
  • The simple /api/reports and /api/datasources registry endpoints do not invoke Central login/ACL checks.

Scheduling

Saving an enabled schedule writes an EnvironmentFile and systemd .service/.timer, symlinks units into /etc/systemd/system by default, reloads systemd, enables the timer, and verifies it. Units run as www-data:www-data, append stdout/stderr to the per-schedule log, and invoke:

php scripts/run_schedule.php <schedule-id>

Manual “Run now” executes synchronously inside the web request. A separate async helper exists for legacy cron_period=now, using shell backgrounding when exec() is available.

The runner requests Tomcat with a 600-second timeout, validates PDF/XLSX signatures, writes a timestamped file, optionally emails it, and updates execution history. HTML, CSV, XLS, and DOCX bodies receive no signature check.

External dependencies

Dependency Role
PostgreSQL Application metadata, Central auth/ACL, and report data
Tomcat 9 + supplied WAR Jasper compilation/fill/export runtime
PostgreSQL JDBC driver Tomcat JNDI datasource connectivity
Apache Alias, rewrite, and reverse proxy
Central service/database Shared session and resource permissions
systemd and sudo Persistent schedules
SMTP relay or local MTA Scheduled email
Materialize/Bootstrap, Google Fonts/icons CDNs Web UI assets
/shared/ui/shell-bootstrap.js Federation shell integration
Optional JasperStarter Upload-time JRXML compilation

Boundaries and limitations

  • The checked-in Java file is a servlet source snapshot, not a buildable WAR project; referenced classes and dependencies are absent.
  • No queue, worker daemon, cache, object storage, retention policy, concurrency control, or distributed scheduler is implemented.
  • No application health/readiness endpoint or metrics/tracing integration exists.
  • Debug code includes unsafe credential/session diagnostics and must not be publicly deployed.