Use Cases#

Business problems Palmyra solves#

Palmyra is built for organisations that need internal, data-heavy web applications delivered fast — and that keep needing more of them. The framework is not a product; it’s the machinery that makes products like these cheaper to build and maintain.

Beyond basic CRUD, Palmyra’s advanced patterns cover approval workflows, child-entity handlers with nested URLs, email notifications, row-level security, filterable dashboards, i18n, and in-app discussion threads — all documented with worked examples.

Healthcare — clinic / hospital management#

Patient registration, appointment scheduling, prescription tracking, pharmacy inventory, billing — every module is a master-data list plus transactional CRUD with a few reports. A clinic application (the framework’s own reference sample) ships Department, Product, Stock, Purchase, Supplier, and User Management screens on top of Palmyra with 24 handlers and 10 React pages.

Manufacturing / supply chain — ERP screens#

Bill of materials, purchase orders, goods-received notes, stock adjustments, vendor ledgers. Each entity is a table with foreign keys and audit trails; screens are grids with filter/sort and forms with lookups. Palmyra’s parentRef flattening and FetchConfig keep list payloads lean across multi-hop joins (part → vendor → country), and SaveHandler upserts simplify sync from barcode scanners or IoT feeds.

Education — student / course administration#

Student registration, course catalogues, enrolment, fee tracking, grade sheets. Every entity follows the same pattern: a master list, a detail view, an edit form, and an export. The CsvHandler / ExcelHandler stream reactive exports so a grade-sheet download for 50 000 students doesn’t stall the server.

Financial services — back-office operations#

Account opening, KYC document management, transaction ledgers, reconciliation dashboards, compliance reporting. Palmyra’s @Permission + the ACL extension enforce per-role visibility on the same handler (query = "TXN_VIEW", export = {"TXN_EXPORT"}), and DropMode.OUTGOING keeps PII out of API responses without shadow DTOs.

Government / public sector — citizen-facing portals#

Licence applications, permit tracking, inspection records, grievance management. Multi-tenant deployments scope every query by tenantId injected in applyQueryFilter; the NativeQueryHandler powers dashboard reports (application counts by district, average processing time) without leaving the handler ecosystem.

Retail / e-commerce — operations back-office#

Product catalogues, order management, inventory, promotions, customer records. The frontend’s MantineServerLookup drives a product picker that queries /product?name=... in real time; the grid’s FilterForm plugin auto-generates a filter panel from the column definitions so operators don’t need a separate search UI.

Human resources — employee management#

The My First Application walkthrough builds exactly this: department master data, employee records with FK lookup, status lifecycle, audit-stamped timestamps. Extend it with leave tracking, payroll stubs, and document uploads (via TusUploadHandler) and you have an HR module.

Multi-tenant SaaS platforms#

Any of the above, sold to multiple customers on shared infrastructure. Palmyra’s handler hooks inject tenant scoping without per-entity code:

@Override
public QueryFilter applyQueryFilter(QueryFilter filter, HandlerContext ctx) {
    filter.addCondition(new SimpleCondition("tenantId", auth.getTenantId()));
    return filter;
}

Every query, every export, every upsert is tenant-isolated from one override in the base handler.


Technical problems Palmyra removes#

Backend#

Problem Without Palmyra With Palmyra
New entity needs a controller + service + repository + SQL 4+ files, 200+ lines 1 annotated POJO + 1 handler component
Client wants different fields per screen Multiple endpoints or GraphQL Client passes _fields, server compiles SELECT
Flatten a parent attribute (e.g. department name on employee row) Hand-written JOIN or DTO projector @PalmyraField(parentRef = "department", attribute = "name")
Required on create, optional on update Two DTOs or runtime if-checks @PalmyraField(mandatory = Mandatory.CREATE)
Audit columns that clients shouldn’t set, hashes that shouldn’t leak Shadow DTO DropMode.INCOMING / DropMode.OUTGOING on the same model
Swap auth providers without changing handlers Rewrite permission checks @Permission resolves through Spring’s standard PermissionEvaluator — swap the bean, keep the annotations
Export millions of rows to CSV/Excel Custom streaming code CsvHandler / ExcelHandler stream reactively out of the box
Schema constraints not in the database Validate in application code @PalmyraMappingConfig declares unique / foreign keys; Palmyra honours them during upserts and lookups

Frontend#

Problem Without Palmyra With Palmyra
Per-entity HTTP fetch/update/delete axios wrapper per resource One PalmyraStoreFactory + an endpoint string
Grid paging, sort, search, refresh-after-save Manual useState + query-string encoding SummaryGrid from a column-definition array
Form state + validation + submit to API React Hook Form + axios + toast PalmyraNewForm / PalmyraEditForm with attribute props
Foreign-key dropdown that queries a second API Custom debounce + fetch + mapping MantineServerLookup with an endpoint + label attribute
Swap MUI ↔ Mantine Rewrite every component Change the import path; data layer is identical
Filter panel for a grid Build per-grid FilterForm plugin auto-generates from column definitions

Who benefits most#

Team / organisation What Palmyra gives them
Small teams building internal tools Ship CRUD screens in days, not weeks — one developer can cover both stacks
Organisations with many similar entities Each new entity = 1 POJO + 1 handler + 5 React files — not a new vertical slice
Teams that own their relational database Raw JDBC, no ORM hiding the schema; responses under 50 ms on normal workloads
Backend teams that don’t want a separate API spec The model IS the contract — no OpenAPI drift, no code generation
Frontend teams tired of per-entity boilerplate One factory, one endpoint string, one attribute prop — done
Regulated industries @Permission + ACL extension + DropMode enforce access control and data masking at the framework level, not scattered through business code

What Palmyra is not designed for#

Honest boundaries — pick the right tool:

Scenario Better fit
Public GraphQL API Hasura, Spring GraphQL
Document / NoSQL database Mongoose, Spring Data MongoDB
Real-time / event-driven streaming Kafka + Spring Cloud Stream, Socket.IO
Zero-config code generation with opinionated scaffolding JHipster
Heavy client-side offline-first state Redux Toolkit, TanStack Query with local persistence

Palmyra shines when the problem is “we have relational tables and we need admin screens, fast, for a lot of entities” — and keeps shining as the entity count grows, because the cost per entity stays flat.


Where to start#

  • Overview — framework positioning and capabilities.
  • Comparison — honest side-by-side with similar frameworks.
  • Concepts — plain-language primer on Palmyra’s moving parts.
  • My First Application — build an Employee + Department app end-to-end.
  • Tutorial — Advanced — 20+ recipes for workflows, dashboards, nested resources, email, ACL, i18n, and more.
  • API Format — the full HTTP contract for mobile / third-party integrators.
  • Reference — per-component API pages.