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 Client Laravel Package

mesd/jasper-client

mesd/jasper-client is a Laravel/PHP client for JasperReports that lets you run reports, pass parameters, and export PDF, HTML, XLS, and other formats from your application through a simple, configurable API.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and inspect the source. composer require mesd/jasper-client (or add it to composer.json manually if Packagist metadata is stale). Because the package is small and sparsely documented, open src/ and read the client class first — that is your real README. Identify the client constructor signature (base URL + credentials), the transport (likely Guzzle 3/4-era), and the available methods (getReports, getReport, getReportOptions, resource helpers, etc.).

  2. Confirm the server side. You need a running JasperReports Server with its REST API reachable, typically at http://host:8080/jasperserver/rest_v2. The account you authenticate with must have read access to the report URIs you will call. Verify with curl -u user:pass http://host:8080/jasperserver/rest_v2/serverInfo before blaming the client.

  3. Wire it into the app config. Put the base URL and credentials in config/services.php / .env, never inline. Instantiate through a small service provider so you can swap the transport later.

  4. First use case: run a parameterless report and save the bytes.

// Illustrative — confirm exact class/method names against src/
$client = new JasperClient(
    'http://jasper.example.com:8080/jasperserver',
    config('services.jasper.username'),
    config('services.jasper.password')
);

$pdf = $client->getReport('/reports/samples/AllAccounts', ['format' => 'pdf']);
file_put_contents(storage_path('app/accounts.pdf'), $pdf);

If that returns a non-empty PDF, the auth + base URL + URI encoding are all correct. Everything else is parameter plumbing.

Implementation Patterns

Two-step "options then render" workflow. This is the pattern you will use most. First, fetch the report's input controls (GET /rest_v2/reports/{uri}/options) to discover parameter names, types, defaults, and allowed values. Render a form from that metadata, then submit to your own controller, which calls the client to run the report with the mapped parameters. Cache the option metadata (minutes to hours) — it changes rarely and is a needless round-trip on every page view.

Wrap the client in a domain service. Do not let controllers call the client directly. A ReportService that exposes options(string $uri): array, run(string $uri, array $params, string $format): StreamedResponse, and listFor(string $folder): array gives you one place to handle errors, timeouts, caching, and format selection.

class JasperReportService
{
    public function __construct(private JasperClient $client) {}

    public function render(string $uri, array $params, string $format): StreamedResponse
    {
        $body = $this->client->getReport($uri, array_merge($params, ['format' => $format]));

        return response()->streamDownload(
            fn () => print($body),
            basename($uri).'.'.$format,
            ['Content-Type' => $this->mime($format)]
        );
    }
}

Choose format by intent. PDF for printable output, xlsx for analyst handoff, csv for machine ingestion, html only for previews. Parameter names/values often need per-format coercion (e.g., a multi-select control wants repeated query keys, not a comma-joined string).

Long-running reports. Reports over a few seconds should not block a web request. Either raise the client/transport timeout and stream to disk, or move to Jasper's asynchronous /reportExecutions endpoints (the package may not cover these — you can add thin methods that reuse its HTTP transport). A queued job + signed URL to the generated file is the usual production shape.

Multi-tenant / per-org auth. Jasper scopes resources by organization. If you serve multiple tenants, keep separate credential sets and build the client per request (or per tenant key in a container binding), rather than reusing one authenticated instance.

Parameter mapping. Dates usually need the server's expected format (yyyy-MM-dd is common, but locale-sensitive controls differ). Booleans often want literal true/false. Preserve report URI slashes — encode the path segments, not the slashes.

Health check + circuit breaker. A cheap serverInfo call on a schedule makes Jasper outages obvious. Wrap report runs so a failed Jasper does not take down the page that hosts the form.

Gotchas and Tips

  • It is a 2014 artifact. Expect PHP 5.x idioms, an old Guzzle constraint, and no typed properties or return types. On PHP 8+ you will likely hit deprecations or hard dependency conflicts. Verify with composer why-not mesd/jasper-client before assuming it installs cleanly alongside a modern Laravel HTTP stack.
  • Check the license. The metadata says NOASSERTION. Read LICENSE / composer.json in the repo before shipping it commercially; if unclear, isolate or reimplement the few REST calls yourself — the API surface you actually need is small.
  • Auth failures can return HTML, not JSON/PDF. Jasper sometimes 302-redirects unauthenticated requests to a login page. If your "report" output starts with <!DOCTYPE html>, you have an auth or path problem, not a report problem. Assert on Content-Type and status before writing bytes.
  • Base URL and /rest_v2 path. Trailing slashes, a missing /rest_v2, or using the old /rest/ path produce confusing 404s. Test the raw curl URL first, then mirror it exactly in config.
  • Report URIs are paths, not query values. "/reports/samples/AllAccounts" — do not URL-encode the slashes. This is the single most common cause of "report not found".
  • Large reports blow memory. The client buffers the response body by default. For big XLSX/PDFs, prefer streaming to disk and setting set_time_limit(0) on the job; consider output compression on the server side.
  • Silent failures are common. The client likely throws a generic exception on any non-2xx, with little context. Wrap calls and log the request URL, status, and response snippet; without that, debugging degrades into packet-sniffing.
  • Date and locale quirks. Parameter values are interpreted in the server's locale. If a date control is ambiguous, send the strict ISO format and verify against the /options metadata's type hints.
  • Session and cookies. Some deployments rely on the JSESSIONID cookie rather than stateless Basic auth. If you see intermittent 401s after the first successful call, your transport is not preserving cookies across the client's requests.
  • Extension points. Subclass the client or decorate it to add retry-with-backoff, request logging, and metrics; inject a custom HTTP client if the bundled Guzzle version is the blocker. Keep these in a thin adapter so a future replacement (Laravel Http:: calls against rest_v2) is a one-file swap.
  • Test against a real server. The package's own tests (if any) are unlikely to cover your server version; a smoke test that runs one tiny report per environment is worth more than unit tests here.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin