sigedi/jasper-report-bundle
A Symfony bundle that integrates JasperReports into your app, letting you configure report templates, pass parameters, and export PDF, HTML, Excel, and other formats from services or controllers with minimal setup.
This bundle is a thin Symfony DI wrapper around jaspersoft/rest-client (the official REST v2 client for JasperReports Server). Almost all behaviour you'll interact with lives in that upstream library, so budget time for its README and the JasperReports Server REST v2 API guide — the bundle just gives you a configured, autowirable client.
Minimum steps:
composer require sigedi/jasper-report-bundle jaspersoft/rest-clientconfig/bundles.php:
Sigedi\JasperReportBundle\JasperReportBundle::class => ['all' => true],
DependencyInjection/Configuration.php first — it is the single source of truth for the config tree. Expect a root key in the sigedi_jasper_report / jasper_report family with host, port, base path, username, password, organization, and possibly Guzzle options.JASPER_HOST, JASPER_USER, JASPER_PASSWORD, JASPER_ORG) so dev/staging/prod differ without code changes.php bin/console debug:container Jaspersoft — the bundle may or may not alias Jaspersoft\Client\Client for autowiring. If it doesn't, add your own alias in config/services.yaml.First use case: a controller that runs a repository report unit and streams it as a PDF download. Resolve the client from the container, call the report service with a /reports/... URI and pdf format, and return the raw bytes.
Wrap it, don't sprinkle it. The client returns PSR-7-ish response bodies and throws Jaspersoft\Exception\RESTRequestException. Put a small ReportRenderer service around it that takes a report URI + parameter array and returns a string or a temp file path. Everything else in your app (controllers, commands, message handlers) talks to that service. This is also your test seam — you can't easily mock Guzzle inside the library, but you can mock your wrapper.
Streaming controller. For downloads:
$response = new Response($renderer->render($uri, 'pdf', $params), 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="report.pdf"',
]);
For large reports, write to a tmpfile() and use BinaryFileResponse — the REST client will otherwise hold the whole document in memory.
Parameter passing. The report service accepts a flat array of input-control values keyed by the exact parameter name defined in the JRXML. Multi-select controls need arrays; date controls need the server's expected format (usually yyyy-MM-dd), not DateTime objects. Get the names from /rest_v2/reports/{uri}/inputControls or the Jaspersoft UI rather than guessing.
Multi-tenant / organization switching. If you run one Jaspersoft instance across tenants, the organization matters on every call. Either build one client per org (cleanest) or set the organization before each request if the bundle exposes a setter — check the vendor source, this is exactly the kind of thing thin bundles get wrong.
Batch and scheduled exports. The same wrapper is useful from a console command (app:reports:export) driven by cron or Messenger. Cache rendered output keyed by hash(uri + params + serverVersion) when the underlying data is slow-changing; JasperReports Server itself caches nothing for you by default.
Error handling. Catch RESTRequestException, inspect getErrorCode() / body, and map 401 (bad creds), 404 (wrong URI/case), and 400 (bad parameters) to distinct exceptions. Log the full server body at debug — Jaspersoft's errors are verbose but only in the payload.
Testing. In functional tests, bind your ReportRenderer wrapper to a stub returning a fixture PDF. Don't let CI hit a real JasperReports Server.
composer.json and be prepared to fork. debug:container and debug:config are your fastest discovery tools.rawurlencode path segments, and verify the path in the Jaspersoft web UI first — a 404 is almost always a path mistake, not an auth problem.pdf and xlsx behave; csv silently ignores pagination, and html output references assets you'll need to inline. If you need paginated Excel, use xlsx with the ignorePagination parameter rather than post-processing.timeout and connect_timeout; if not, decorate the client service and inject a pre-configured GuzzleHttp\Client.How can I help you explore Laravel packages today?