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

Rest Client Laravel Package

jaspersoft/rest-client

A Laravel/PHP client for the JasperReports Server REST API. Run reports, export results to PDF, Excel, and other formats, and manage reports, folders, and resources from your app with a simple, fluent interface. Handles authentication and common server operations for quick reporting integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer — there are no Laravel-specific service providers, so this is a plain library:

composer require jaspersoft/rest-client

Instantiate the Client with your server URL, credentials, and (optionally) an organization ID. The URL must include the /jasperserver context path when JRS is deployed under the default servlet context:

use Jaspersoft\Client\Client;

$client = new Client(
    'https://reports.example.com/jasperserver',
    env('JASPER_USER'),
    env('JASPER_PASSWORD'),
    env('JASPER_ORG', null) // organization ID for multi-tenant servers
);

Where to look first:

  1. README — lists the available services and gives copy-paste examples per service.
  2. src/Jaspersoft/Client/Client.php — exposes service accessors (reportService(), jobService(), resourceService(), userService(), organizationService(), roleService(), permissionService(), importExportService()). This method list is your API map.
  3. src/Jaspersoft/Dto/ — the Data Transfer Objects that mirror JasperReports Server's JSON payloads. If you need to know what fields a resource or job accepts, they're here.

First use case — run a report and save the output:

$pdf = $client->reportService()->runReport(
    '/reports/samples/AllAccounts', // repository URI of the report unit
    'pdf'
);

Storage::put('reports/all-accounts.pdf', $pdf);

Before you wire this into anything, verify connectivity with $client->serverInfo() — it's the cheapest call that proves URL, credentials, and organization scope are all correct.

Implementation Patterns

Wrap the client in a Laravel service. Don't new Client() in controllers. Bind a configured singleton so credentials and the base URL live in config/services.php:

// config/services.php
'jasperserver' => [
    'url'      => env('JASPER_URL'),
    'username' => env('JASPER_USER'),
    'password' => env('JASPER_PASSWORD'),
    'org_id'   => env('JASPER_ORG'),
],

// AppServiceProvider::register()
$this->app->singleton(Client::class, fn () => new Client(
    config('services.jasperserver.url'),
    config('services.jasperserver.username'),
    config('services.jasperserver.password'),
    config('services.jasperserver.org_id'),
));

Then inject Client (or, better, your own thin ReportGateway wrapper) into jobs and controllers.

Synchronous report execution is fine for small reports and dashboard widgets:

$csv = $client->reportService()->runReport(
    '/reports/ops/daily-sales',
    'csv',
    ['StartDate' => $from->format('Y-m-d'), 'EndDate' => $to->format('Y-m-d')],
    null,                 // pages: "1-3", "1,4", or null for all
    'report_'             // attachments prefix for HTML/embedded images
);

Asynchronous execution via the job service is the pattern for anything slow or large. Create a job, poll it, then fetch the output. This keeps HTTP requests short and lets you put the work on a queue:

use Jaspersoft\Dto\Job\Job;
use Jaspersoft\Dto\Job\JobSource;
use Jaspersoft\Dto\Job\SimpleTrigger;

$job = new Job();
$job->label = 'daily-sales-'.$date;
$job->source = new JobSource('/reports/ops/daily-sales');
$job->trigger = new SimpleTrigger('daily-trigger', 'DAILY', 1);
$created = $client->jobService()->createJob($job);

For ad-hoc (non-scheduled) runs, prefer runReport and push it into a ShouldQueue job rather than building one-off JRS jobs — you keep retries and observability in Laravel where you can see them.

Resource management — creating reports, folders, data sources, or input controls is a matter of building the matching DTO and posting it:

$folder = new \Jaspersoft\Dto\Resource\Folder(name: 'Ops Reports', label: 'Operations');
$client->resourceService()->createResource('/reports/ops', $folder);

Use resourceService()->getResourceDescriptor($uri) to inspect existing resources and searchResources($query, $type) to build pickers for user-driven report selection.

Permissions and multi-tenancy — permissionService() handles per-resource ACLs and organizationService() + userService() handle tenant provisioning. When you onboard a new tenant, a typical flow is: create the organization, create its users and roles, then importExportService()->import() a catalog zip into the new tenant's folder. This is the single most valuable use of the library for SaaS-style apps.

Output handling — runReport returns a binary string. For anything you'll keep, stream it straight to a file or an S3 upload instead of holding it in memory, and serve it back with a signed URL rather than re-running the report per request.

Gotchas and Tips

Guzzle/version conflicts are the biggest practical risk. The library was written against older Guzzle releases; depending on which version you pull, you may hit dependency resolution conflicts with a modern Laravel app (Guzzle 7) or with packages that pin Symfony/PSR versions. Check composer.json of the version you install before committing, and be prepared to either constrain the library version or fork and bump its HTTP client. Score is only 6.7 and dependents are zero — treat dependency maintenance as your responsibility.

LGPL-3.0 is not MIT. You can use the library in a closed-source application, but if you modify and redistribute it, the modifications must be released. For a typical SaaS you're fine; for a distributed desktop/on-prem product, review with counsel.

Credentials are not encrypted in transit by the library. Always run JRS behind HTTPS in production. Self-signed JasperReports test servers will fail SSL verification; rather than disabling verification globally (a real security hole), point the client at a properly trusted certificate or use an internal CA.

Organization scoping is easy to get wrong. An admin user of organizations/tenantA will see tenant A's resources only. If runReport returns a 404 for a report you can see in the web UI, the org ID in the constructor is the first thing to check — not the resource URI.

URI conventions matter. Report paths are repository URIs (/reports/...) and must begin with a slash. Trailing slashes on the server URL cause double-slash paths that some proxies reject.

Large outputs will exhaust memory. runReport buffers the entire response. A 200 MB PDF will die at your memory_limit. Either fetch in the job service with pagination or increase the limit on the execution that streams to disk, and always write to php://temp or a stream rather than file_get_contents-style round-trips.

Errors surface as exceptions, not status codes. Wrap calls in try/catch and map JRS error payloads (which carry useful messages) to your own exception types. Distinguish 401 (bad credentials/org), 404 (URI or tenant scope), and 5xx (report compile failure — this often means a data source is down, not that your request was wrong).

Timeouts need to be deliberate. Long reports can exceed default HTTP timeouts. Pass a longer timeout at construction where supported, and for anything over a minute prefer the job service or a queued job so a web request never blocks on JRS.

No first-class streaming or lazy iteration — resource searches return full descriptor objects, which can be heavy on catalogs with thousands of items. Paginate your own queries and cache descriptor lookups that don't change (data sources, folders, input controls).

Testing and local development. The library has no built-in mock layer. Abstract it behind an interface and bind a fake in tests; if you need HTTP-level fidelity, run a JasperReports container and point the client at it, keeping the fixture reports in version control alongside your tests.

Extension points are limited. There are no events or middleware hooks. If you need retries, circuit-breaking, or request logging, that lives in your wrapper around the Client — and because the library owns its HTTP client internally, retries generally mean catching the exception at your layer and re-calling the service, not hooking into Guzzle.

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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core