ReadHandler#
com.palmyralabs.palmyra.handlers.ReadHandler
Single-record read endpoint. Returns one object identified by the {id} path placeholder — the primary key of the table mapped through @CrudMapping.type.
Request / response shape#
- HTTP:
GET <secondaryMapping>— e.g.GET /api/masterdata/industrySector/42. - Request body: none.
- Response body: a single JSON object carrying every attribute declared on the model class from
@CrudMapping.type, minus any field flaggedDropMode.OUTGOING. Not wrapped — just the object.
{
"id": 42,
"name": "Health Care",
"code": "HC",
"createdAt": "2026-04-01T09:12:00Z"
}Internally the endpoint operates from a FilterCriteria / QueryFilter split (similar to QueryHandler but narrowed to a single-row lookup).
Methods#
| Method | Signature |
|---|---|
aclCheck |
int aclCheck(HandlerContext ctx) |
preApplyCriteria |
void preApplyCriteria(FilterCriteria criteria, HandlerContext ctx) — default copies ctx.getParams() into the criteria |
applyFilter |
QueryFilter applyFilter(QueryFilter filter, HandlerContext ctx) |
onQueryResult |
Tuple onQueryResult(Tuple tuple, Action action) |
Example#
@Component
@CrudMapping(value = "/v1/admin/user/{id}", type = User.class)
public class UserReadHandler implements ReadHandler {
@Autowired
private UserProvider userProvider;
@Override
public int aclCheck(HandlerContext ctx) {
return userProvider.hasRole("USER_READ") ? 0 : -1;
}
@Override
public void preApplyCriteria(FilterCriteria criteria, HandlerContext ctx) {
ReadHandler.super.preApplyCriteria(criteria, ctx);
criteria.addAttribute("requestedBy", userProvider.getUserId());
}
@Override
public QueryFilter applyFilter(QueryFilter filter, HandlerContext ctx) {
// restrict to records owned by the calling user
filter.addCondition("userId", userProvider.getUserId());
return filter;
}
@Override
public Tuple onQueryResult(Tuple tuple, Action action) {
// strip sensitive columns before returning
tuple.remove("passwordHash");
return tuple;
}
}