skip to content

How do @RepositoryRestResource and @RestResource change the URL path and HAL link relation of an exposed resource, and how do path and rel differ?

level: middleimportance: should knowfreq 40%

answer

  1. path = URL segment; rel = _links key
  2. independent knobs, both default to derived name
  3. @RepositoryRestResource: collectionResourceRel + itemResourceRel
  4. @RestResource: single rel, on query method or property
  5. rename rel = breaking for hypermedia clients

basics

~20 s

path sets the URL segment (e.g. /members); rel sets the name of the link in the HAL _links output that clients follow. @RepositoryRestResource customizes the whole collection; @RestResource customizes a single query method or association.

solid answer

~40 s

Both annotations expose the same two knobs but at different scopes. `path` is the literal URL segment a client hits; `rel` (collectionResourceRel/itemResourceRel on @RepositoryRestResource, or rel on @RestResource) is the *link relation name* — the key under `_links` in HAL that a hypermedia client uses to discover the URL. They are independent: you can serve at `/members` while keeping the rel `people`, or vice versa. `@RepositoryRestResource` sits on the repository interface and governs the collection/item resources. `@RestResource` is the fine-grained sibling placed on individual query methods (customizing their path under `/search`) or on entity properties/associations. Getting `rel` right matters because well-behaved clients navigate by rel, not by hardcoded URLs.

code

java · 14 lines
java
@RepositoryRestResource(
    path = "members",            // URL: /members
    collectionResourceRel = "people", // HAL _links key stays 'people'
    itemResourceRel = "person")
public interface PersonRepository extends JpaRepository<Person, Long> {

    // Reachable at /members/search/by-surname (URL) with _links rel 'bySurname'
    @RestResource(path = "by-surname", rel = "bySurname")
    List<Person> findByLastName(@Param("name") String lastName);

    // Query method present in Java but NOT exposed over REST
    @RestResource(exported = false)
    List<Person> findByFirstName(String firstName);
}

go deeper

for a junior

Know that path changes the URL and there's a way to rename the HAL link.

for a middle

Clearly articulate path (URL) vs rel (HAL _links key) and which annotation applies at which scope.

for a senior

Explain why the decoupling exists and that renaming a rel breaks hypermedia clients even when URLs are unchanged.

for a principal

Treat rels as part of the API contract; govern rel/path changes with the same versioning discipline as any published interface.

**Two annotations, two scopes.** Spring Data REST offers a coarse-grained annotation and a fine-grained one: - `@RepositoryRestResource` — on the **repository interface**, controls the repository's collection and item resources. - `@RestResource` — on a **query method** (a `findBy…` method) or on an **entity property/association**, controls that specific sub-resource. Both carry the same conceptual attributes: `path`, `rel`, and `exported`. **path vs rel — the crucial distinction.** - `path` is the **URL segment**. If `path = "members"` on the repository, the collection is served at `GET /members` and items at `/members/{id}`. For a query method, `@RestResource(path = "by-surname")` makes it reachable at `/people/search/by-surname`. - `rel` is the **link relation** — the *name/key* under the `_links` object of HAL output. A hypermedia client asks 'give me the link with rel X' and follows the `href` it finds. Changing `rel` does **not** change the URL; changing `path` does not change the rel unless you also set it. On `@RepositoryRestResource` the rel is split into two attributes: `collectionResourceRel` (rel of the whole collection, e.g. in the root/profile listing) and `itemResourceRel` (rel of a single item link). On `@RestResource` there is a single `rel` attribute because it targets one sub-resource. **Why they are independent.** SDR deliberately decouples the human/URL layer from the machine/navigation layer. A team can rename a URL (`/people` → `/members`) for cosmetic reasons while keeping the stable rel `people` so existing hypermedia clients keep working — or the reverse. **Defaults.** If you omit `path`, it defaults to the derived resource name (pluralized entity name for the collection, method name for a query method). If you omit `rel`, it defaults to the same derived name. So unset attributes fall back to sensible auto-generated values. **Where @RestResource shines.** 1. **Query methods:** rename an ugly derived method path — `findByLastNameStartingWith` → `path = "nameStartsWith"` under `/search`. 2. **Associations/properties:** rename or hide an association link on an entity, e.g. `@RestResource(path = "addr", rel = "addr")` on a `@OneToOne Address address` field, or `exported = false` to drop the association resource. **Gotchas.** (1) `rel` changes are invisible if you only test with a browser hitting URLs — you must inspect the `_links` JSON to see them. (2) A `path` with characters needing encoding, or clashing with another resource's path, causes ambiguous routing. (3) `@RestResource` on a *non-query* CRUD method has no effect — only exported query methods and properties honor it. (4) Renaming a rel is a breaking change for hypermedia clients that navigate by that rel.

  • You changed collectionResourceRel but the URL didn't change — is that a bug?
    No. collectionResourceRel only renames the link relation in the HAL _links output. To change the URL you must set path. They are deliberately independent.
  • Can @RestResource customize a save() or delete() method?
    No. @RestResource on a method only affects exported query (derived finder) methods placed under /search. CRUD methods from CrudRepository are handled by the collection/item resources and aren't customized this way.

saying these in an interview costs you the question

  • Claiming rel changes the URL
  • Using @RestResource expecting it to rename the whole collection
  • Renaming a rel and assuming it's non-breaking for clients

context