What is HAL, and what do the _links and _embedded properties in a Spring Data REST response mean?
answer
- application/hal+json default
- _links = rels + hrefs (self)
- _embedded = inlined collection/related
- EntityModel/CollectionModel/PagedModel
- page block + first/next/prev/last
basics
~10 sHAL (Hypertext Application Language) is the default JSON format Spring Data REST returns. _links holds URLs to related resources (like self), and _embedded holds the actual related or collection data inline.
solid answer
~30 sHAL is a hypermedia JSON convention (media type application/hal+json) that Spring Data REST uses by default. Every resource carries a _links object mapping link relations (rel names like self, or an association name) to hrefs, so clients navigate by following links instead of hardcoding URLs. Collections and related resources are placed under _embedded, keyed by the relation name (usually the pluralised entity name), each item again carrying its own _links. Spring HATEOAS builds these representations via EntityModel, CollectionModel, and PagedModel; paged responses also add a page object (size, totalElements, number) plus first/next/prev/last navigation links. This makes the API self-describing and discoverable.
code
java · 11 lines@Entity
public class Book {
@Id @GeneratedValue Long id;
String title;
@ManyToOne Author author; // becomes an 'author' link, not inlined
}
@RepositoryRestResource
public interface BookRepository extends JpaRepository<Book, Long> { }
// GET /books -> _embedded.books[*] each with _links.self + _links.author,
// plus top-level _links + page metadata.go deeper
Must know HAL is the default, and that _links = navigation, _embedded = inlined data.
Should explain EntityModel/CollectionModel/PagedModel and the page metadata block.
Should discuss id exposure, @Relation renaming, and association links being lazy references.
Frames HAL as a discoverability contract and weighs it against HAL-FORMS and client coupling concerns.
**HAL** stands for *Hypertext Application Language* — a simple convention for embedding hyperlinks and related data into JSON. Its media type is `application/hal+json`, and it is the **default output format of Spring Data REST**. The goal is HATEOAS (Hypermedia As The Engine Of Application State): responses tell the client where it can go next via links, rather than the client hardcoding URL patterns. **The two reserved properties:** - **`_links`** — an object whose keys are *link relations* (`rel`) and whose values contain an `href`. Every resource has at least a `self` link (its canonical URL). For each JPA association on the entity, Spring Data REST adds a link named after that association, whose href points to a sub-resource you can follow to load the related entity/entities. Example: a `Book` resource exposes `self` and `author` links. - **`_embedded`** — an object holding *inlined* resource data so the client does not have to make another request. For a **collection** endpoint (e.g. `GET /books`), the actual list lives under `_embedded.books` (the key is the relation name, normally the pluralised, lower-cased entity name; customisable with `@Relation`). Each embedded item is itself a full HAL resource with its own `_links.self`. **Who builds this:** Spring Data REST delegates to **Spring HATEOAS**, whose representation model classes are `EntityModel<T>` (single item + links), `CollectionModel<T>` (list + links), and `PagedModel<T>` (adds a `page` metadata block). The serializer for HAL is `Jackson2HalModule`. **Paging:** When a repository returns a `Page`, the HAL body includes a top-level `page` object with `size`, `totalElements`, `totalPages`, and `number`, plus `_links` for `first`, `prev`, `next`, and `last` when applicable. **Example shape of `GET /books`:** ```json { "_embedded": { "books": [ { "title": "Dune", "_links": { "self": {"href": "/books/1"}, "author": {"href": "/books/1/author"} } } ] }, "_links": { "self": {"href": "/books?page=0&size=20"}, "profile": {"href": "/profile/books"} }, "page": { "size": 20, "totalElements": 1, "totalPages": 1, "number": 0 } } ``` **Common gotchas:** - The `href` for associations is a *link to follow*, not the embedded object — the association is lazy by default and not inlined unless you use a projection/excerpt. - The `profile` link points to ALPS/JSON-Schema metadata describing the resource, generated automatically. - Entity `id` fields are *not* serialised into the JSON body by default — the identity is expressed through the `self` link's href. You can force ids to appear with `RepositoryRestConfiguration.exposeIdsFor(...)`. **When to use HAL:** it is the sensible default for a hypermedia REST API where clients discover capabilities dynamically. If you need affordance metadata (which HTTP methods and fields are valid), step up to HAL-FORMS.
- Why doesn't the entity's numeric id appear in the JSON body by default?Spring Data REST expresses identity through the self link's href, keeping the payload URL-driven. You can override this with RepositoryRestConfiguration.exposeIdsFor(Book.class) in a RepositoryRestConfigurer.
- Under what key does a collection endpoint place its items, and how do you change it?Under _embedded keyed by the pluralised, lower-cased entity name (e.g. _embedded.books). Change it by annotating the entity with @Relation(collectionRelation = "...").
saying these in an interview costs you the question
- Thinking _embedded always inlines related entities (associations are links unless a projection/excerpt embeds them)
- Believing the id field is always in the JSON body
- Confusing _links.self with a link to a different resource