Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Jasper Report Bundle Laravel Package

hboie/jasper-report-bundle

Symfony bundle for generating reports with JasperReports. Compile JRXML templates and export to PDF, HTML, XLS, and other formats through a simple PHP service, with configurable JasperReports binaries and report parameters.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: hboie/jasper-report-bundle is a Symfony bundle, not a Laravel package. It has no service provider, no facade, and no auto-discovery for Laravel. If you're in a Laravel app you have two realistic paths:

  1. Recommended for Laravel: composer require jaspersoft/rest-client and wrap it in your own tiny service provider + singleton. You get 90% of what the bundle gives you (config + a configured client) in ~40 lines.
  2. Only if you're straddling a Symfony/Laravel codebase: install the bundle in the Symfony side and expose reports via an internal HTTP endpoint your Laravel app calls.

Assuming you go with option 1 (or you're reading the bundle for reference), the mental model the bundle encodes is the same:

  • Config — host, port, username, password, organization (tenant), and optionally a base path or SSL flags. As of v1.6 there is also a timeout configuration option, which the bundle maps onto the underlying HTTP client. Look at the bundle's DependencyInjection/Configuration.php to see the exact key names (host, port, username, password, organization, timeout, etc.) before copying them into config/services.php / a config/jasper.php.
  • Service — the bundle registers a container service wrapping Jaspersoft\Client\Client. In Laravel, register your own singleton in AppServiceProvider and resolve credentials from config() / .env.
  • First use case — run a report that already exists on the JasperReports Server and return a PDF:
$client = app(\Jaspersoft\Client\Client::class);

$pdf = $client->reportService()->runReport(
    '/reports/invoices/monthly',
    'pdf',
    null,           // output format is first arg in some versions; check your client version
    null,
    ['customer_id' => 42]
);

return response($pdf)
    ->header('Content-Type', 'application/pdf')
    ->header('Content-Disposition', 'inline; filename="monthly.pdf"');

Where to look first: the repo's README and DependencyInjection/ folder, then the jaspersoft/rest-client source — the bundle is a thin config layer over that client, so the real API surface lives there. Also confirm which JasperReports Server version you're targeting; the REST v2 endpoints changed around 6.x/7.x.

Implementation Patterns

Bind the client as a singleton, configure once. In AppServiceProvider::register():

$this->app->singleton(\Jaspersoft\Client\Client::class, function () {
    $client = new \Jaspersoft\Client\Client(
        config('jasper.host'),
        config('jasper.port'),
        config('jasper.username'),
        config('jasper.password'),
        config('jasper.org_id') // tenant
    );

    // Timeout support added in bundle v1.6 — mirror it here.
    // Set per-request timeout on the underlying HTTP client / Guzzle handler.
    $client->setTimeout(config('jasper.timeout', 60));

    return $client;
});

Treat this like any other HTTP SDK binding — never new it inside controllers. Keep the timeout in config/jasper.php (defaulting from .env) so it is tunable per environment, matching how the bundle now exposes it.

Wrap it in a domain service. Don't let controllers touch Jaspersoft\Client\Client directly. A ReportService with methods like renderInvoice(int $id): string and renderPayslip(...) keeps parameter marshalling (dates, multi-select arrays, locale strings) in one place and gives you a seam for tests and caching.

Queue long-running reports. Jasper renders can take 5–60s. Pattern: dispatch a GenerateReportJob, store the output on Storage::disk('s3'), then poll an endpoint or broadcast completion. Avoid doing this on the request thread — you'll blow PHP max_execution_time before Jasper finishes. Set the client timeout slightly above your realistic worst-case render, not the other way around.

Stream downloads, don't buffer twice. For anything over a few hundred KB, use response()->streamDownload() with the raw binary from runReport, or write it straight to storage. The client returns the body as a string, so keep an eye on memory for large reports.

Validate and pre-format parameters before calling Jasper. Jasper is strict: date params usually want yyyy-MM-dd, multi-value params want arrays, and nulls vs. empty strings behave differently. Write a small ReportParameters value object and format in PHP, not in JRXML expressions.

Multi-tenant / multi-organization. Jasper's organization parameter scopes the login. If you have per-customer Jasper orgs, build a small factory that resolves the org from the authenticated user and instantiates a scoped client (with Cache::store('redis')->remember() on it if credentials rotate slowly). Don't share a single client across tenants.

Health check. Add a scheduled command that calls something cheap like fetching the repository root or a known resource, so Jasper outages surface before users hit the report page. Give it a short timeout (the new v1.6 timeout config is useful here — keep the health-check timeout well below the report timeout).

Gotchas and Tips

  • Not maintained since Nov 2021. Symfony 2–5 only, and JasperReports Server has moved on. Pin the Symfony version if you're on the Symfony side, and expect to patch the Guzzle dependency yourself. For Laravel, skip the bundle — the direct client is more honest about the compatibility story. v1.6 (timeout config) is a small quality-of-life addition, not a revival of the maintenance story.
  • Timeout config (v1.6) is a wrapper, not the whole story. The new timeout option gives you control over the HTTP-level timeout, but Jasper's server-side report timeout is separate and still exists. Set both. Also note v1.6 only adds a single timeout value — if you need distinct connect_timeout vs. read timeout behavior, you still have to reach into the underlying HTTP client / Guzzle handler directly. Verify in vendor/ which timeout key the release actually reads and where it is applied.
  • Client API drift. The Jaspersoft\Client\Client method signatures (especially runReport's argument order for format vs. params) differ between 1.x/2.x branches. Read the actual source in vendor/ rather than relying on blog posts.
  • Authentication quirks. Older Jasper versions use cookie-based j_spring_security_check; newer ones prefer /rest_v2/login with Basic auth. If you get 401s that "sometimes work," it's almost always session cookie handling — the client has an AuthenticationException path for this.
  • Self-signed certs. Internal Jasper deployments frequently use self-signed certs. The bundle/config may not expose Guzzle's verify => false; you'll need to reach into the client or bind a custom Guzzle handler. Prefer installing the CA cert over disabling verification.
  • Timeouts still bite. Even with the v1.6 option, an unset/infinite Guzzle timeout will hang workers. Always set an explicit timeout value in config (and a sane default in .env), and be aware that setting it too low yields truncated/failed reports rather than clean errors — Jasper may still be rendering server-side.
  • Parameter encoding. Multi-select arrays must be passed as arrays, not comma strings. Dates as ISO strings. Boolean params sometimes want literal "true" strings depending on JRXML expression use. Test each report's parameter contract once, then codify it in your ReportParameters class.
  • Debugging: enable Guzzle request logging (Log::debug) by passing a handler to the client, and cross-check against Jasper's own jasperserver.log. The response body from a failing Jasper call is usually the real error message — don't swallow it behind a generic 500. Distinguish a timeout (client gave up) from a Jasper error (server returned a message).
  • Extension points in the bundle (if you're using Symfony): override the service definition via services.yaml, decorate the client with a decorator that adds logging or retry, and override Configuration.php derived config keys (including the new timeout) via hboie_jasper_report.yml. In Laravel your extension point is simpler: a JasperClientFactory interface bound to a concrete implementation, swapped in tests.
  • Testing. Fake the client with a JasperClientContract interface and return pre-baked PDF bytes from fixtures. Never hit a real Jasper server in your test suite — it's slow and stateful. Assert that your timeout config is actually plumbed through to the client in a unit test, since this is exactly the kind of setting that silently regresses.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums